From 0df1f179059a80adcb83e7d8df3f4ab61461e8eb Mon Sep 17 00:00:00 2001 From: Steve Paltridge Date: Fri, 8 May 2026 03:03:23 -0600 Subject: [PATCH 1/2] Add marketing site (/site) + agent-os toolkit + Pages workflow Consolidates the recall.works marketing site and the agent-os toolkit into the canonical RecallWorks/Recall repo. - /site: 8 HTML pages (index, whitepaper, pillars, architecture, brain, hardware, comparison, quickstart) + assets, sitemap.xml, robots.txt, CNAME (www.recall.works), OG card. - /agent-os: installable cold-start toolkit (bootstrap, brain stub, templates, helper scripts). - /.github/workflows/pages.yml: deploys /site to GitHub Pages on push to main when site/** changes. After merge: enable GitHub Pages with custom domain www.recall.works, update DNS CNAME to recallworks.github.io, archive the duplicative stevepaltridge/recall.works repo. --- .github/workflows/pages.yml | 41 ++ agent-os/.gitignore | 45 ++ agent-os/LICENSE | 25 ++ agent-os/README.md | 76 ++++ agent-os/bin/_README.md | 40 ++ agent-os/bin/brain-snapshot.ps1 | 97 ++++ agent-os/bin/latest-revival.ps1 | 73 +++ agent-os/bin/mark-touched.ps1 | 38 ++ agent-os/bin/qwen-coldstart.ps1 | 112 +++++ agent-os/bin/qwen-rolling-summary.ps1 | 167 +++++++ agent-os/bin/spend-gate.ps1 | 79 ++++ agent-os/bin/transcript-tail.ps1 | 53 +++ agent-os/bin/vault-promote.ps1 | 93 ++++ agent-os/bin/vault-sync.ps1 | 95 ++++ agent-os/bootstrap.ps1 | 128 ++++++ agent-os/brain/Dockerfile | 37 ++ agent-os/brain/README.md | 81 ++++ agent-os/brain/agency_sidecar_patch.md | 55 +++ agent-os/brain/docker-compose.yml | 36 ++ agent-os/brain/recall.py | 46 ++ agent-os/config.example.json | 58 +++ agent-os/docs/QUICKSTART.md | 95 ++++ agent-os/install.sh | 41 ++ agent-os/templates/00-routing.md.tmpl | 38 ++ agent-os/templates/REVIVAL-template.md | 55 +++ agent-os/templates/audit-trail.md.tmpl | 34 ++ agent-os/templates/fix-at-root-reflex.md.tmpl | 46 ++ site/CNAME | 1 + site/architecture.html | 235 ++++++++++ site/assets/og-card.png | Bin 0 -> 187826 bytes site/assets/og-card.svg | 22 + site/assets/site.css | 176 ++++++++ site/brain.html | 208 +++++++++ site/comparison.html | 137 ++++++ site/hardware.html | 120 +++++ site/index.html | 136 ++++++ site/pillars.html | 109 +++++ site/quickstart.html | 217 +++++++++ site/robots.txt | 5 + site/sitemap.xml | 12 + site/whitepaper.html | 419 ++++++++++++++++++ 41 files changed, 3581 insertions(+) create mode 100644 .github/workflows/pages.yml create mode 100644 agent-os/.gitignore create mode 100644 agent-os/LICENSE create mode 100644 agent-os/README.md create mode 100644 agent-os/bin/_README.md create mode 100644 agent-os/bin/brain-snapshot.ps1 create mode 100644 agent-os/bin/latest-revival.ps1 create mode 100644 agent-os/bin/mark-touched.ps1 create mode 100644 agent-os/bin/qwen-coldstart.ps1 create mode 100644 agent-os/bin/qwen-rolling-summary.ps1 create mode 100644 agent-os/bin/spend-gate.ps1 create mode 100644 agent-os/bin/transcript-tail.ps1 create mode 100644 agent-os/bin/vault-promote.ps1 create mode 100644 agent-os/bin/vault-sync.ps1 create mode 100644 agent-os/bootstrap.ps1 create mode 100644 agent-os/brain/Dockerfile create mode 100644 agent-os/brain/README.md create mode 100644 agent-os/brain/agency_sidecar_patch.md create mode 100644 agent-os/brain/docker-compose.yml create mode 100644 agent-os/brain/recall.py create mode 100644 agent-os/config.example.json create mode 100644 agent-os/docs/QUICKSTART.md create mode 100644 agent-os/install.sh create mode 100644 agent-os/templates/00-routing.md.tmpl create mode 100644 agent-os/templates/REVIVAL-template.md create mode 100644 agent-os/templates/audit-trail.md.tmpl create mode 100644 agent-os/templates/fix-at-root-reflex.md.tmpl create mode 100644 site/CNAME create mode 100644 site/architecture.html create mode 100644 site/assets/og-card.png create mode 100644 site/assets/og-card.svg create mode 100644 site/assets/site.css create mode 100644 site/brain.html create mode 100644 site/comparison.html create mode 100644 site/hardware.html create mode 100644 site/index.html create mode 100644 site/pillars.html create mode 100644 site/quickstart.html create mode 100644 site/robots.txt create mode 100644 site/sitemap.xml create mode 100644 site/whitepaper.html diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..b3c2cf5 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,41 @@ +# @recall.works | .github/workflows/pages.yml | v1.0 | 2026-05-08 | deploy /site to GitHub Pages on push +name: Deploy site to GitHub Pages + +on: + push: + branches: [main] + paths: + - 'site/**' + - '.github/workflows/pages.yml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload site artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/agent-os/.gitignore b/agent-os/.gitignore new file mode 100644 index 0000000..2809fe5 --- /dev/null +++ b/agent-os/.gitignore @@ -0,0 +1,45 @@ +# OS / editor noise +.DS_Store +Thumbs.db +*.swp +*.swo +*~ +.vscode/ +.idea/ + +# Local config — never commit +config.json +.env +.env.* +!.env.example + +# Generated state +state/ +logs/ +*.log +*.bak +*.bak-* +.spend-gate-last +.qwen-killswitch +.vault-killswitch + +# Local model state +ollama/ +*.gguf + +# Local-only secrets (paranoia layer) +*.key +*.pem +*-key.txt +.vault-key.txt + +# Sealed backups (never commit, never search) +*.SEALED.zip +_sealed-*/ + +# Build / scratch +_scratch/ +_build/ +node_modules/ +__pycache__/ +*.pyc diff --git a/agent-os/LICENSE b/agent-os/LICENSE new file mode 100644 index 0000000..eb9d1d9 --- /dev/null +++ b/agent-os/LICENSE @@ -0,0 +1,25 @@ +MIT License + +Copyright (c) 2026 Steve Paltridge / Recall™ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +The "Recall" word mark is a trademark of Steve Paltridge (application +pending). Use of the mark in derivative works or republished material should +acknowledge the source. Use of the code is fully unrestricted under MIT. diff --git a/agent-os/README.md b/agent-os/README.md new file mode 100644 index 0000000..f332da7 --- /dev/null +++ b/agent-os/README.md @@ -0,0 +1,76 @@ + + +# Recall™ · Agent OS + +**A reference architecture for durable AI coding work.** + +When AI coding agents stay long enough to do real work, they hit three walls: + +1. **Statelessness** — every conversation starts cold; memory is whatever the host platform decides to keep. +2. **Cost** — autonomous loops can burn tokens or cloud spend faster than you can intervene. +3. **Audit** — what survives is the chat scrollback, until an opaque summarizer compacts it. + +Agent OS is six composable pillars and a small set of conventions that turn any AI coding agent into a contractor with a project log instead of a goldfish. + +> Read the whitepaper: **** +> _(or open `site/agent-os.html` locally — same content, no internet required)_ + +--- + +## What this repo contains + +``` +agent-os/ +├── README.md ← you are here +├── LICENSE ← MIT +├── config.example.json ← copy to config.json and edit +├── bootstrap.ps1 ← Windows install: dirs + scheduled tasks + templates +├── install.sh ← cross-platform follow-up (v0.2) +├── bin/ ← reference-implementation scripts (PowerShell, no deps) +├── templates/ ← starter memory files (routing, audit-trail, REVIVAL) +├── brain/ ← networked-brain container blueprint (v0.2) +└── docs/ ← QUICKSTART + design notes +``` + +## Status + +**v0.1 · seed.** This is the initial public skeleton. The whitepaper is finished. The reference scripts work in place (running in production at the originating workstation right now). What's published here is being de-personalized — names, paths, account IDs being replaced by config knobs — one script at a time. Each script's header tells you whether it's `READY` or still has a `TODO: de-personalize` notice. + +Pull requests welcome. Issues welcome. The pattern is what matters; the code is one valid implementation. + +## Get the bits + +Three options, ordered by ambition: + +**1. Read the whitepaper, build your own.** Everything you need is at . The pattern is the deliverable. + +**2. Copy a script, run it on your machine.** Every script in `bin/` is self-contained PowerShell with a parameter block at the top. No global state, no install ceremony. + +**3. Bootstrap the whole thing.** + +```powershell +# Windows / PowerShell 7+ +git clone https://github.com/recall-works/agent-os +cd agent-os +cp config.example.json config.json +# edit config.json — set workspace path, storage account, ceiling +.\bootstrap.ps1 +``` + +That registers the scheduled tasks, drops the memory templates into the spot your editor's memory tool reads from, and runs a self-test of the spend gate. + +## What's not here yet + +- The brain container (networked vector recall) — design notes in `brain/README.md`, full Docker image in v0.2. +- Bash / macOS bootstrap — coming with v0.2. +- Multi-agent coordination wedge (`claim` / `release` / `handoff`) — drops in on top of the brain layer; v0.3. + +## License + +MIT (see `LICENSE`). Use this however you want. Attribution to **Recall™** appreciated. + +## Why "Recall"? + +Because the whole architecture is built around one question: *what does the agent recall when it sits down tomorrow?* If the answer is "whatever VS Code felt like keeping," you have a problem. Recall makes the answer "exactly what you wrote down on purpose." + +— Steve Paltridge · diff --git a/agent-os/bin/_README.md b/agent-os/bin/_README.md new file mode 100644 index 0000000..e9fc09f --- /dev/null +++ b/agent-os/bin/_README.md @@ -0,0 +1,40 @@ +# Recall · Agent OS — bin/ + +Reference implementation scripts. PowerShell 7+, no dependencies beyond what +your platform already needs (Azure CLI for vault scripts, ollama for qwen +scripts). + +Every script: + +- reads `config.json` from the repo root (or the path passed via `-Config`) +- honors a kill-switch file (path defined in `config.json`) +- can run in `-DryRun` mode where applicable +- exits non-zero on any failure (fail-closed) + +| Script | Purpose | Status | +|------------------------------|------------------------------------------------------------------|--------| +| `spend-gate.ps1` | Provider-side cost ceiling check (fail-closed) | READY | +| `vault-sync.ps1` | Nightly snapshot of workspace + memory dir to draft container | READY | +| `vault-promote.ps1` | Weekly sweep of >N-day draft blobs into WORM vault container | READY | +| `brain-snapshot.ps1` | Weekly zip of brain state → vault + sealed local copy | READY | +| `mark-touched.ps1` | Log a folder so vault-sync picks it up next run | READY | +| `transcript-tail.ps1` | Locate active editor transcript and emit last N KB | READY | +| `qwen-rolling-summary.ps1` | Periodic local-model summary of active session → memory dir | READY | +| `qwen-coldstart.ps1` | One-shot orientation brief from memory + newest revival doc | READY | +| `latest-revival.ps1` | Print newest revival doc, qwen-compressed if >24h old | READY | + +## Conventions + +- All `*.ps1` files take a `-Config ` parameter (default: `..\config.json`). +- All log files land under `..\logs\` (gitignored). +- All state files (last-call timestamps, etc.) land under `..\state\`. +- All scripts accept `-DryRun` where it makes sense. + +## Adapting to your environment + +The originals at `c:\Dev\tools\` (in the originating workstation) had hard-coded +paths and account names. The public versions read everything from `config.json`. + +If you're porting these to bash/zsh, the public-facing logic is intentionally +small — each script under 200 lines. The PowerShell sugar is mostly +`Invoke-RestMethod` and `azcopy` orchestration. diff --git a/agent-os/bin/brain-snapshot.ps1 b/agent-os/bin/brain-snapshot.ps1 new file mode 100644 index 0000000..2bccd96 --- /dev/null +++ b/agent-os/bin/brain-snapshot.ps1 @@ -0,0 +1,97 @@ +# @recall.works/agent-os | brain-snapshot.ps1 | v1.0 +# Weekly zip of the brain's persistent state -> WORM vault + sealed local copy. +# The "brain" is whatever vector store you're running (ChromaDB, Qdrant, etc.). +# This script captures its data dir verbatim. +# +# Usage: pwsh ./brain-snapshot.ps1 [-Config ../config.json] [-DryRun] + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [switch] $DryRun +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +$repoRoot = Split-Path $Config + +$kill = Join-Path $repoRoot $cfg.spendGate.killSwitchFile +if (Test-Path $kill) { Write-Error "brain-snapshot ABORT: kill switch present"; exit 99 } +& (Join-Path $PSScriptRoot 'spend-gate.ps1') -Config $Config -Quiet +if ($LASTEXITCODE -ne 0 -and -not $DryRun) { Write-Error "brain-snapshot ABORT: spend-gate denied"; exit 98 } + +# --- inputs --- +# By convention, brain state lives at /brain/store or you set it explicitly. +$brainSrc = if ($cfg.brain.stateDir) { + [System.Environment]::ExpandEnvironmentVariables($cfg.brain.stateDir) +} else { + Join-Path ([System.Environment]::ExpandEnvironmentVariables($cfg.workspace.secondary)) 'brain\store' +} +if (-not (Test-Path $brainSrc)) { Write-Error "brain source not found: $brainSrc (set 'brain.stateDir' in config.json)"; exit 3 } + +$sealedDir = Join-Path $repoRoot 'state\sealed-brain-backups' +if (-not (Test-Path $sealedDir)) { New-Item -ItemType Directory -Path $sealedDir -Force | Out-Null } + +# Sentinel files +$donot = Join-Path $sealedDir 'DO-NOT-READ.txt' +if (-not (Test-Path $donot)) { +@' +SEALED COLD-STORAGE BRAIN BACKUPS. + +DO NOT READ. DO NOT INDEX. DO NOT TREAT AS LIVE STATE. + +These zips are renamed .SEALED.zip on purpose so the agent does not +mistake them for active brain content. Live brain is your container/ +service. Authoritative cold-copy is in the WORM vault. These local zips +exist only as last-resort keepsake. + +To restore: rename .SEALED.zip -> .zip, expand to a fresh location, +verify integrity manually before pointing services at it. +'@ | Set-Content -Path $donot -Encoding UTF8 +} +'*' | Set-Content -Path (Join-Path $sealedDir '.gitignore') -Encoding ASCII + +$ts = Get-Date -Format 'yyyy-MM-dd_HHmmss' +$zipPath = Join-Path $sealedDir "brain-$ts.SEALED.zip" + +"==== brain-snapshot $ts ====" +"src: $brainSrc" +"sealed: $zipPath" + +if ($DryRun) { "DRYRUN: would zip + upload + rotate"; exit 0 } + +# Stage with excludes (.venv, __pycache__, *.tmp) +$tempStage = Join-Path $env:TEMP "brain-stage-$ts" +New-Item -ItemType Directory -Path $tempStage | Out-Null +$excludes = @('.venv','__pycache__','tmp','*.tmp') +robocopy $brainSrc $tempStage /E /XD ($excludes | ForEach-Object { Join-Path $brainSrc $_ }) /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null +if ($LASTEXITCODE -ge 8) { Write-Error "robocopy failed: $LASTEXITCODE"; Remove-Item $tempStage -Recurse -Force; exit 4 } + +Compress-Archive -Path "$tempStage\*" -DestinationPath $zipPath -CompressionLevel Optimal +Remove-Item $tempStage -Recurse -Force + +$zipMB = [math]::Round((Get-Item $zipPath).Length / 1MB, 2) +"sealed local: $zipPath ($zipMB MB)" + +# Upload to vault +$SA = $cfg.vault.storageAccount +$vault = $cfg.vault.vaultContainer +$keyFile = Join-Path $repoRoot $cfg.vault.keyFile +$KEY = (Get-Content $keyFile -Raw).Trim() -replace '^KEY=','' +$expiry = (Get-Date).ToUniversalTime().AddHours(2).ToString('yyyy-MM-ddTHH:mm:ssZ') +$sas = az storage container generate-sas --account-name $SA --account-key $KEY --name $vault ` + --permissions rwc --expiry $expiry --https-only -o tsv +$remote = "https://$SA.blob.core.windows.net/$vault/brain/snap-$ts/brain.zip?$sas" +azcopy copy $zipPath $remote --log-level WARNING +if ($LASTEXITCODE -ne 0) { Write-Error "azcopy failed: $LASTEXITCODE"; exit 5 } +"vault uploaded: $vault/brain/snap-$ts/brain.zip" + +# Rotate sealed local: keep newest 2 +Get-ChildItem $sealedDir -Filter 'brain-*.SEALED.zip' | + Sort-Object LastWriteTime -Descending | + Select-Object -Skip 2 | + ForEach-Object { "rotating out (local): $($_.Name)"; Remove-Item $_.FullName -Force } + +"==== brain-snapshot complete ====" diff --git a/agent-os/bin/latest-revival.ps1 b/agent-os/bin/latest-revival.ps1 new file mode 100644 index 0000000..5a02621 --- /dev/null +++ b/agent-os/bin/latest-revival.ps1 @@ -0,0 +1,73 @@ +# @recall.works/agent-os | latest-revival.ps1 | v1.0 +# Print newest REVIVAL doc(s), qwen-compressed if older than 24h. +# +# Usage: +# pwsh ./latest-revival.ps1 # newest, raw if <24h or qwen-compressed +# pwsh ./latest-revival.ps1 -Topic sp -N 2 # 2 newest matching REVIVAL-S*-sp*.md +# pwsh ./latest-revival.ps1 -Raw # always raw + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [int] $N = 1, + [switch] $Raw, + [string] $Topic = '' +) + +$ErrorActionPreference = 'Stop' +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json + +$revDir = Join-Path ([System.Environment]::ExpandEnvironmentVariables($cfg.workspace.primary)) 'REVIVAL' +if (-not (Test-Path $revDir)) { Write-Error "no revival dir at $revDir"; exit 3 } + +$pattern = if ($Topic) { "REVIVAL-S*-$Topic*.md" } else { 'REVIVAL-S*.md' } +$docs = Get-ChildItem -Path $revDir -Filter $pattern | + Where-Object { $_.Name -notmatch '\.compact\.md$' } | + Sort-Object LastWriteTime -Descending | Select-Object -First $N +if (-not $docs) { Write-Error "no revival docs match $pattern"; exit 4 } + +foreach ($doc in $docs) { + $ageH = ((Get-Date) - $doc.LastWriteTime).TotalHours + Write-Output "===== $($doc.Name) ===== ($([int]$ageH)h old, $([int]($doc.Length/1024))KB)" + + if ($Raw -or $ageH -lt 24) { + Get-Content $doc.FullName -Raw + continue + } + + $cacheFile = Join-Path $revDir ("$($doc.BaseName).compact.md") + $cacheValid = (Test-Path $cacheFile) -and ((Get-Item $cacheFile).LastWriteTime -gt $doc.LastWriteTime) + + if (-not $cacheValid) { + $prompt = @' +You are compressing a session-recovery doc into telegraphese. +Output sections in order: +1. status: 1 line. CLOSED|OPEN|BLOCKED + 1-line state. +2. blockers: bullets of what's stuck + why. +3. next-action: 1-3 bullets, the next concrete step. +4. untested: bullets of what was NOT verified. +5. files: paths touched, comma-separated. +PRESERVE: file paths, hex sigs, identifiers, REVIVAL-* refs. +DROP: prose, articles, pronouns. Use → + : ; for connectors. +60 lines max total. +'@ + $body = Get-Content $doc.FullName -Raw + $payload = @{ + model = $cfg.localModel.model + prompt = "$prompt`n`n=== INPUT ===`n$body" + stream = $false + options = @{ temperature = 0.2; num_ctx = 16384 } + } | ConvertTo-Json -Depth 5 -Compress + + try { + $resp = Invoke-RestMethod -Uri 'http://127.0.0.1:11434/api/generate' -Method Post -Body $payload -ContentType 'application/json' -TimeoutSec 120 + $resp.response | Set-Content -Path $cacheFile -Encoding UTF8 + } catch { + Write-Output "[qwen unavailable, raw fallback] $($_.Exception.Message)" + Get-Content $doc.FullName -Raw + continue + } + } + Get-Content $cacheFile -Raw +} diff --git a/agent-os/bin/mark-touched.ps1 b/agent-os/bin/mark-touched.ps1 new file mode 100644 index 0000000..1e1f4a3 --- /dev/null +++ b/agent-os/bin/mark-touched.ps1 @@ -0,0 +1,38 @@ +# @recall.works/agent-os | mark-touched.ps1 | v1.0 +# Append a folder/file path to the touched-folders log so the next vault-sync +# run will back it up. Idempotent. +# +# Usage: +# pwsh ./mark-touched.ps1 'C:\Some\External\Folder' [-Why "reason"] +# pwsh ./mark-touched.ps1 ~/.config/something [-Why "reason"] + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, Position=0)] [string] $Path, + [string] $Why = '', + [string] $Config = (Join-Path $PSScriptRoot '..\config.json') +) + +$repoRoot = if (Test-Path $Config) { Split-Path $Config } else { Split-Path $PSScriptRoot } +$logFile = Join-Path $repoRoot 'state\agent-touched-folders.log' +if (-not (Test-Path (Split-Path $logFile))) { New-Item -ItemType Directory -Path (Split-Path $logFile) -Force | Out-Null } + +$abs = (Resolve-Path -LiteralPath $Path -ErrorAction SilentlyContinue).Path +if (-not $abs) { $abs = $Path } # log even if doesn't exist yet + +if (-not (Test-Path $logFile)) { + @( + '# agent-touched-folders.log', + '# format: one absolute path per line. blank/# lines ignored.', + '# vault-sync.ps1 reads this and backs up each path.', + '' + ) | Set-Content -Path $logFile -Encoding ASCII +} + +$existing = Get-Content $logFile | Where-Object { $_ -and -not $_.StartsWith('#') } | + ForEach-Object { ($_ -split '#',2)[0].Trim() } +if ($existing -contains $abs) { "already tracked: $abs"; return } + +$comment = if ($Why) { " # $Why ($(Get-Date -Format 'yyyy-MM-dd'))" } else { " # ($(Get-Date -Format 'yyyy-MM-dd'))" } +Add-Content -Path $logFile -Value "$abs$comment" +"marked: $abs" diff --git a/agent-os/bin/qwen-coldstart.ps1 b/agent-os/bin/qwen-coldstart.ps1 new file mode 100644 index 0000000..9cc5c14 --- /dev/null +++ b/agent-os/bin/qwen-coldstart.ps1 @@ -0,0 +1,112 @@ +# @recall.works/agent-os | qwen-coldstart.ps1 | v1.0 +# Generate a cold-start orientation brief from active memory + newest revival +# doc, using the local model. Zero user-tokens. +# +# Usage: +# pwsh ./qwen-coldstart.ps1 # generic brief, prints to stdout +# pwsh ./qwen-coldstart.ps1 -Topic foo # topic-focused +# pwsh ./qwen-coldstart.ps1 -Save # write to memories/_coldstart-brief.md + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [string] $Topic = '', + [switch] $Save +) + +$ErrorActionPreference = 'Stop' +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json + +$memDir = [System.Environment]::ExpandEnvironmentVariables($cfg.memory.memoriesDir) +if (-not (Test-Path $memDir)) { Write-Error "memory dir missing: $memDir"; exit 3 } + +# State-bearing files only (skip protocol/anti-pattern reference files) +$stateFiles = @('00-routing.md','03-preferences.md','05-audit-trail.md') +$mems = $stateFiles | ForEach-Object { Get-Item (Join-Path $memDir $_) -ErrorAction SilentlyContinue } | Where-Object { $_ } + +$memBlob = ($mems | ForEach-Object { + $body = Get-Content $_.FullName -Raw + if ($_.Name -eq '05-audit-trail.md') { + $rows = ($body -split "`n") | Where-Object { $_ -match '^\| S-' } + $tail = $rows | Select-Object -First 40 + $body = "
`n" + ($tail -join "`n") + } + "===== $($_.Name) =====`n$body" +}) -join "`n`n" + +# Newest revival doc +$revBlob = '' +$revDir = Join-Path ([System.Environment]::ExpandEnvironmentVariables($cfg.workspace.primary)) 'REVIVAL' +if (Test-Path $revDir) { + $pat = if ($Topic) { "REVIVAL-S*-$Topic*.md" } else { 'REVIVAL-S*.md' } + $newest = Get-ChildItem $revDir -Filter $pat | + Where-Object { $_.Name -notmatch '\.compact\.md$' } | + Sort-Object LastWriteTime -Descending | Select-Object -First 1 + if ($newest) { + $revBlob = "===== NEWEST REVIVAL ($($newest.Name)) =====`n$(Get-Content $newest.FullName -Raw)" + } +} + +$intent = if ($Topic) { "topic-focused cold-start brief for: $Topic" } else { "generic cold-start brief across all active workstreams" } + +$prompt = @" +You are generating a cold-start orientation brief for an AI agent that is about to +start a session. The agent already has hard guardrails. You produce only the +"what's currently going on" digest. + +INTENT: $intent + +OUTPUT — exactly these sections, in order, telegraphese throughout: +## active sessions +- one bullet per OPEN session in audit-trail. format: S-id | agent | 1-line state. +- 5-8 bullets max. newest first. + +## current focus +- 1-3 bullets. what is the agent likely walking into? cite REVIVAL doc + S-id. + +## recent decisions (last 7 days) +- bullets of architecture/preference choices that future-me must honor. + +## blockers / gotchas +- bullets of failure modes flagged in REVIVAL or audit. include untested callouts. + +## tools to remember +- 3-5 bullets of scripts, commands, file paths the agent will reach for. + +RULES: +- Drop articles/pronouns. Use → + : ; symbols. PRESERVE: file paths, hex sigs, version numbers, identifiers, REVIVAL-* refs. +- 60 lines max total. +- No preamble. No code fences. Start with "## active sessions". + +INPUT: +$memBlob + +$revBlob +"@ + +$payload = @{ + model = $cfg.localModel.model + prompt = $prompt + stream = $false + options = @{ temperature = 0.15; num_ctx = 32768; num_predict = 1200 } +} | ConvertTo-Json -Depth 5 -Compress + +try { + $resp = Invoke-RestMethod -Uri 'http://127.0.0.1:11434/api/generate' -Method Post -Body $payload -ContentType 'application/json' -TimeoutSec 300 + $brief = $resp.response.Trim() +} catch { + Write-Error "qwen call failed: $($_.Exception.Message)" + exit 4 +} + +$header = "`n" +$out = $header + $brief + +if ($Save) { + $savePath = Join-Path $memDir '_coldstart-brief.md' + $out | Set-Content -Path $savePath -Encoding UTF8 + Write-Host "wrote $savePath ($($out.Length) chars)" +} else { + Write-Output $out +} diff --git a/agent-os/bin/qwen-rolling-summary.ps1 b/agent-os/bin/qwen-rolling-summary.ps1 new file mode 100644 index 0000000..8061dc5 --- /dev/null +++ b/agent-os/bin/qwen-rolling-summary.ps1 @@ -0,0 +1,167 @@ +# @recall.works/agent-os | qwen-rolling-summary.ps1 | v1.0 +# Periodic local-model summarization of the active session transcript into a +# durable markdown file under the agent's memory dir. Zero cost (local model), +# zero user-tokens. +# +# Usage: pwsh ./qwen-rolling-summary.ps1 [-Config ../config.json] [-Force] +# +# Idempotent: skips if the transcript hasn't grown by `MinGrowthKB` since last run. + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [int] $TailKB = 80, + [int] $MinGrowthKB = 20, + [switch] $Force +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +$repoRoot = Split-Path $Config + +$kill = Join-Path $repoRoot $cfg.localModel.killSwitchFile +if (Test-Path $kill) { Write-Error "qwen-rolling-summary ABORT: kill switch present"; exit 99 } + +$ollama = (Get-Command ollama -ErrorAction SilentlyContinue).Source +if (-not $ollama) { Write-Error "ollama not on PATH"; exit 3 } +$model = $cfg.localModel.model + +# --- locate active transcript --- +$tdir = [System.Environment]::ExpandEnvironmentVariables( + $cfg.memory.transcriptsDir.Replace('', $cfg.memory.workspaceId) +) +if (-not (Test-Path $tdir)) { Write-Error "transcripts dir missing: $tdir"; exit 4 } +$active = Get-ChildItem $tdir -Filter *.jsonl -ErrorAction SilentlyContinue | + Sort-Object LastWriteTime -Descending | Select-Object -First 1 +if (-not $active) { Write-Host "[rolling-summary] no transcript yet"; exit 0 } +$sid = [System.IO.Path]::GetFileNameWithoutExtension($active.Name) + +# --- output target (memory dir, session subdir) --- +$memDir = [System.Environment]::ExpandEnvironmentVariables($cfg.memory.memoriesDir) +$outDir = Join-Path $memDir 'session' +if (-not (Test-Path $outDir)) { New-Item -ItemType Directory -Path $outDir -Force | Out-Null } +$outFile = Join-Path $outDir "$sid-rolling.md" + +$stateDir = Join-Path $repoRoot 'state' +if (-not (Test-Path $stateDir)) { New-Item -ItemType Directory -Path $stateDir -Force | Out-Null } +$stateFile = Join-Path $stateDir "rolling-summary-$sid.state" + +# --- growth check --- +$currentMark = "$($active.LastWriteTimeUtc.Ticks):$($active.Length)" +if (-not $Force -and (Test-Path $stateFile)) { + $prev = (Get-Content $stateFile -Raw).Trim() + if ($prev) { + $prevSize = [int64]($prev -split ':')[1] + $growKB = ($active.Length - $prevSize) / 1KB + if ($growKB -lt $MinGrowthKB) { + Write-Host "[rolling-summary] skip — grew $([math]::Round($growKB,1)) KB (threshold $MinGrowthKB)" + exit 0 + } + } +} + +# --- pull tail --- +$tailFile = Join-Path $env:TEMP "transcript-tail-$sid.jsonl" +& (Join-Path $PSScriptRoot 'transcript-tail.ps1') -Config $Config -TailKB $TailKB -OutFile $tailFile | Out-Null +if (-not (Test-Path $tailFile)) { Write-Error "tail not produced"; exit 5 } +$tailText = Get-Content $tailFile -Raw -Encoding UTF8 +$tailText = [regex]::Replace($tailText, "\x1b\[[0-9;]*[A-Za-z]", '') +$tailText = [regex]::Replace($tailText, '[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]', '') + +# --- pre-extract conversational turns (user.message/assistant.message + selected tool calls) --- +$turns = New-Object System.Collections.Generic.List[string] +foreach ($line in ($tailText -split "`n")) { + if ([string]::IsNullOrWhiteSpace($line)) { continue } + try { $obj = $line | ConvertFrom-Json -ErrorAction Stop } catch { continue } + switch ($obj.type) { + 'user.message' { + $c = $obj.data.content + if ($c -and $c.Trim()) { $turns.Add("USER: $($c.Trim())") } + } + 'assistant.message' { + $c = $obj.data.content + if ($c -and $c.Trim()) { $turns.Add("ASSISTANT: $($c.Trim())") } + if ($obj.data.toolRequests) { + foreach ($tr in $obj.data.toolRequests) { + if ($tr.name -in 'run_in_terminal','create_file','replace_string_in_file','multi_replace_string_in_file') { + try { + $a = $tr.arguments | ConvertFrom-Json -ErrorAction Stop + $hint = $a.command + if (-not $hint) { $hint = $a.filePath } + if (-not $hint) { $hint = $a.explanation } + if ($hint) { + $oneline = ($hint -replace '\s+',' ') + $entry = "TOOL[$($tr.name)]: $oneline" + if ($entry.Length -gt 300) { $entry = $entry.Substring(0,300) } + $turns.Add($entry) + } + } catch {} + } + } + } + } + } +} +$dialogue = ($turns -join "`n`n") +if (-not $dialogue) { Write-Warning "no conversational turns extracted"; exit 6 } + +$prompt = @" +You are a session archivist. Below is a USER/ASSISTANT dialogue with selected +TOOL calls noted inline. Produce ONLY a structured markdown summary using these +EXACT headings, in this order: + +## Verbatim user directives +## Decisions made +## Files touched +## Open threads +## Last operational state + +Rules: +- Quote the user's exact words for any directives. Keep quotes short. +- Preserve exact paths, version numbers, identifiers verbatim. +- For "Files touched" list paths from TOOL[create_file]/TOOL[replace_string_in_file]/TOOL[multi_replace_string_in_file] entries. +- If a section has nothing, write `(none)` under it. +- Do NOT echo raw input. Do NOT add a preamble. Do NOT refuse. +- Total output under 1500 words. + +DIALOGUE: +$dialogue +"@ + +$tmpPrompt = Join-Path $env:TEMP "rolling-prompt-$sid.txt" +[System.IO.File]::WriteAllText($tmpPrompt, $prompt, [System.Text.UTF8Encoding]::new($false)) + +$start = Get-Date +$errLog = Join-Path $env:TEMP "rolling-stderr-$sid.log" +$body = Get-Content $tmpPrompt -Raw -Encoding UTF8 | & $ollama run $model 2>$errLog +$elapsed = ((Get-Date) - $start).TotalSeconds + +if (-not $body -or ($body -join '').Trim().Length -lt 50) { + Write-Warning "qwen returned empty/near-empty (prompt $([math]::Round((Get-Item $tmpPrompt).Length/1KB,1)) KB)" + if (Test-Path $errLog) { Get-Content $errLog -Tail 5 | ForEach-Object { Write-Warning " $_" } } + exit 7 +} + +$now = Get-Date +$header = @" + + + +# Rolling Summary — session $sid + +_Last updated: $($now.ToString('yyyy-MM-dd HH:mm:ss')) · transcript $([math]::Round($active.Length/1KB,1)) KB_ + +"@ + +[System.IO.File]::WriteAllText($outFile, $header + ($body -join "`n"), [System.Text.UTF8Encoding]::new($false)) +[System.IO.File]::WriteAllText($stateFile, $currentMark, [System.Text.UTF8Encoding]::new($false)) + +[pscustomobject]@{ + Session = $sid + OutFile = $outFile + QwenSeconds = [math]::Round($elapsed,1) + SummaryBytes = (Get-Item $outFile).Length + TranscriptKB = [math]::Round($active.Length/1KB,1) +} diff --git a/agent-os/bin/spend-gate.ps1 b/agent-os/bin/spend-gate.ps1 new file mode 100644 index 0000000..526ccad --- /dev/null +++ b/agent-os/bin/spend-gate.ps1 @@ -0,0 +1,79 @@ +# @recall.works/agent-os | spend-gate.ps1 | v1.0 +# Provider-side cost ceiling. Fail-closed. +# +# Usage: pwsh ./spend-gate.ps1 [-Config ../config.json] [-Quiet] +# +# Called by every billable script BEFORE doing anything that costs money. +# Exits 0 = OK to proceed. Non-zero = ABORT. +# +# Designed to fail SAFE: if the cost API itself errors, we DON'T proceed. +# +# Currently implements Azure provider via `az consumption usage list`. +# Adapt the Layer-3 block to your provider (AWS Cost Explorer, GCP billing). + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [switch] $Quiet +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "spend-gate: config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json + +$ceilingUSD = [double]$cfg.spendGate.monthlyCeilingUSD +$failClosed = [bool]$cfg.spendGate.failClosed +$cacheSecs = [int]$cfg.spendGate.cacheSeconds +$kill = Join-Path (Split-Path $Config) $cfg.spendGate.killSwitchFile +$stateDir = Join-Path (Split-Path $Config) 'state' +if (-not (Test-Path $stateDir)) { New-Item -ItemType Directory -Path $stateDir -Force | Out-Null } +$lastCall = Join-Path $stateDir '.spend-gate-last' + +# --- Layer 1: kill switch --- +if (Test-Path $kill) { Write-Error "spend-gate ABORT: kill switch present at $kill"; exit 99 } + +# --- Layer 2: cooldown / cache --- +if (Test-Path $lastCall) { + $age = (Get-Date) - (Get-Item $lastCall).LastWriteTime + if ($age.TotalSeconds -lt $cacheSecs) { + $cached = (Get-Content $lastCall -Raw).Trim() + if ($cached -match '^PASS') { exit 0 } else { exit 1 } + } +} + +# --- Layer 3: query month-to-date spend (Azure) --- +$startOfMonth = (Get-Date -Day 1).ToString('yyyy-MM-dd') +$today = (Get-Date).ToString('yyyy-MM-dd') + +try { + $sub = az account show --query id -o tsv 2>$null + if (-not $sub) { + if ($failClosed) { Write-Error "spend-gate FAIL-CLOSED: az not logged in"; exit 1 } + else { "PASS-NODATA" | Set-Content $lastCall; exit 0 } + } + + $usage = az consumption usage list --start-date $startOfMonth --end-date $today ` + --query "[].pretaxCost" -o tsv 2>$null + if ($LASTEXITCODE -ne 0) { + if (-not $Quiet) { Write-Warning "spend-gate: consumption API unavailable; proceeding without cost data" } + "PASS-NODATA" | Set-Content $lastCall + exit 0 + } + + $numeric = @($usage | Where-Object { $_ -match '^\s*-?\d+(\.\d+)?\s*$' } | ForEach-Object { [double]$_ }) + $mtd = if ($numeric.Count) { [math]::Round(($numeric | Measure-Object -Sum).Sum, 2) } else { 0 } + + if ($mtd -ge $ceilingUSD) { + Write-Error "spend-gate ABORT: MTD `$$mtd >= ceiling `$$ceilingUSD" + "BLOCK: $mtd / $ceilingUSD" | Set-Content $lastCall + exit 1 + } + + if (-not $Quiet) { "spend-gate OK: MTD `$$mtd / ceiling `$$ceilingUSD" } + "PASS: $mtd / $ceilingUSD" | Set-Content $lastCall + exit 0 +} catch { + if ($failClosed) { Write-Error "spend-gate FAIL-CLOSED: $_"; exit 1 } + else { "PASS-ERROR" | Set-Content $lastCall; exit 0 } +} diff --git a/agent-os/bin/transcript-tail.ps1 b/agent-os/bin/transcript-tail.ps1 new file mode 100644 index 0000000..353c708 --- /dev/null +++ b/agent-os/bin/transcript-tail.ps1 @@ -0,0 +1,53 @@ +# @recall.works/agent-os | transcript-tail.ps1 | v1.0 +# Locate the active editor's chat transcript (currently: GitHub Copilot Chat +# under VS Code) and emit the last N KB. +# +# Usage: pwsh ./transcript-tail.ps1 [-Config ../config.json] [-TailKB 200] [-OutFile path] + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [int] $TailKB = 200, + [string] $OutFile = (Join-Path $env:TEMP 'transcript-tail.jsonl') +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +$tdir = [System.Environment]::ExpandEnvironmentVariables( + $cfg.memory.transcriptsDir.Replace('', $cfg.memory.workspaceId) +) +if (-not (Test-Path $tdir)) { Write-Error "transcripts dir not found: $tdir (set memory.workspaceId in config.json)"; exit 3 } + +$active = Get-ChildItem $tdir -Filter *.jsonl | + Sort-Object LastWriteTime -Descending | + Select-Object -First 1 +if (-not $active) { Write-Error "no transcript files in $tdir"; exit 4 } + +$bytes = $TailKB * 1KB +$startOffset = [Math]::Max(0, $active.Length - $bytes) + +$fs = [System.IO.File]::OpenRead($active.FullName) +try { + $fs.Seek($startOffset, 'Begin') | Out-Null + $buf = New-Object byte[] ($active.Length - $startOffset) + [void]$fs.Read($buf, 0, $buf.Length) +} finally { $fs.Dispose() } + +$text = [System.Text.Encoding]::UTF8.GetString($buf) +if ($startOffset -gt 0) { + $nl = $text.IndexOf("`n") + if ($nl -ge 0) { $text = $text.Substring($nl + 1) } +} + +[System.IO.File]::WriteAllText($OutFile, $text, [System.Text.UTF8Encoding]::new($false)) + +[pscustomobject]@{ + Transcript = $active.Name + SessionId = [System.IO.Path]::GetFileNameWithoutExtension($active.Name) + FullSizeKB = [math]::Round($active.Length / 1KB, 1) + TailKB = [math]::Round($buf.Length / 1KB, 1) + OutFile = $OutFile + LastWriteUtc = $active.LastWriteTimeUtc +} diff --git a/agent-os/bin/vault-promote.ps1 b/agent-os/bin/vault-promote.ps1 new file mode 100644 index 0000000..1a3fa0c --- /dev/null +++ b/agent-os/bin/vault-promote.ps1 @@ -0,0 +1,93 @@ +# @recall.works/agent-os | vault-promote.ps1 | v1.0 +# Sweep blobs older than N days from the mutable "draft" container into the +# WORM "vault" container, then delete the draft copy. Resume-safe. +# +# Usage: pwsh ./vault-promote.ps1 [-Config ../config.json] [-DaysOld 30] [-DryRun] +# +# This is the only script in the system that issues a delete, and it deletes +# only against draft. The vault container has time-based immutability set at +# the platform layer; the cloud refuses delete attempts there regardless of +# permissions. Belt + suspenders. + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [int] $DaysOld = 30, + [switch] $DryRun +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +$repoRoot = Split-Path $Config + +# --- gates --- +$kill = Join-Path $repoRoot $cfg.spendGate.killSwitchFile +if (Test-Path $kill) { Write-Error "vault-promote ABORT: kill switch present"; exit 99 } +& (Join-Path $PSScriptRoot 'spend-gate.ps1') -Config $Config -Quiet +if ($LASTEXITCODE -ne 0 -and -not $DryRun) { Write-Error "vault-promote ABORT: spend-gate denied"; exit 98 } + +# --- log --- +$logDir = Join-Path $repoRoot 'logs' +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } +$ts = Get-Date -Format 'yyyy-MM-dd_HHmmss' +$log = Join-Path $logDir "promote-$ts.log" +Start-Transcript -Path $log -Append | Out-Null + +try { + $SA = $cfg.vault.storageAccount + $draft = $cfg.vault.draftContainer + $vault = $cfg.vault.vaultContainer + $keyFile = Join-Path $repoRoot $cfg.vault.keyFile + if (-not (Test-Path $keyFile)) { Write-Error "key file missing: $keyFile"; exit 3 } + $KEY = (Get-Content $keyFile -Raw).Trim() -replace '^KEY=','' + + $cutoff = (Get-Date).ToUniversalTime().AddDays(-$DaysOld) + "== promote $draft -> $vault | older than $DaysOld days ($($cutoff.ToString('yyyy-MM-dd'))) ==" + + $blobs = az storage blob list --account-name $SA --account-key $KEY --container-name $draft ` + --query "[].{name:name, lastModified:properties.lastModified, size:properties.contentLength}" -o json | ConvertFrom-Json + $old = @($blobs | Where-Object { [datetime]$_.lastModified -lt $cutoff }) + "found $($blobs.Count) draft blobs ; $($old.Count) eligible for promotion" + + if ($old.Count -eq 0) { return } + + "indexing vault container for resume-safety..." + $vaultBlobs = az storage blob list --account-name $SA --account-key $KEY --container-name $vault ` + --query "[].name" -o tsv + $vaultSet = @{} + foreach ($n in $vaultBlobs) { if ($n) { $vaultSet[$n] = $true } } + + if ($DryRun) { + $already = @($old | Where-Object { $vaultSet.ContainsKey($_.name) }).Count + "[dry-run] candidates=$($old.Count) | already-in-vault=$already | would-copy=$($old.Count - $already)" + return + } + + $expiry = (Get-Date).ToUniversalTime().AddHours(2).ToString('yyyy-MM-ddTHH:mm:ssZ') + $srcSas = az storage container generate-sas --account-name $SA --account-key $KEY --name $draft --permissions rl --expiry $expiry --https-only -o tsv + $dstSas = az storage container generate-sas --account-name $SA --account-key $KEY --name $vault --permissions wc --expiry $expiry --https-only -o tsv + + $copied = 0; $skipped = 0; $failed = 0 + foreach ($b in $old) { + if ($vaultSet.ContainsKey($b.name)) { + az storage blob delete --account-name $SA --account-key $KEY --container-name $draft --name $b.name --delete-snapshots include 2>&1 | Out-Null + $skipped++ + continue + } + $srcUrl = "https://$SA.blob.core.windows.net/$draft/$($b.name)?$srcSas" + $dstUrl = "https://$SA.blob.core.windows.net/$vault/$($b.name)?$dstSas" + $r = & azcopy copy $srcUrl $dstUrl --overwrite=false --log-level=ERROR 2>&1 + if ($LASTEXITCODE -eq 0) { + az storage blob delete --account-name $SA --account-key $KEY --container-name $draft --name $b.name --delete-snapshots include 2>&1 | Out-Null + $copied++ + } else { + Write-Warning "failed: $($b.name) | $r" + $failed++ + } + } + "== promote complete | promoted=$copied | skipped=$skipped | failed=$failed ==" +} finally { + Stop-Transcript | Out-Null +} diff --git a/agent-os/bin/vault-sync.ps1 b/agent-os/bin/vault-sync.ps1 new file mode 100644 index 0000000..7f66bc7 --- /dev/null +++ b/agent-os/bin/vault-sync.ps1 @@ -0,0 +1,95 @@ +# @recall.works/agent-os | vault-sync.ps1 | v1.0 +# Snapshot workspace + agent memory dir to a "draft" object-storage container. +# Designed to run nightly. Cool tier; promotion to WORM happens via vault-promote.ps1. +# +# Usage: pwsh ./vault-sync.ps1 [-Config ../config.json] [-DryRun] +# +# Provider: Azure Blob Storage (azcopy + az). To use AWS S3, swap the SAS +# generation block for a presigned URL and replace `azcopy sync` with +# `aws s3 sync`. The structure is the same. + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot '..\config.json'), + [switch] $DryRun +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path $Config)) { Write-Error "vault-sync: config not found: $Config"; exit 2 } +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +$repoRoot = Split-Path $Config + +# --- gates --- +$kill = Join-Path $repoRoot $cfg.spendGate.killSwitchFile +if (Test-Path $kill) { Write-Error "vault-sync ABORT: kill switch present"; exit 99 } +& (Join-Path $PSScriptRoot 'spend-gate.ps1') -Config $Config -Quiet +if ($LASTEXITCODE -ne 0 -and -not $DryRun) { Write-Error "vault-sync ABORT: spend-gate denied"; exit 98 } + +# --- inputs --- +$primary = [System.Environment]::ExpandEnvironmentVariables($cfg.workspace.primary) +$memDir = [System.Environment]::ExpandEnvironmentVariables($cfg.memory.memoriesDir) +$mcpJson = Join-Path $env:APPDATA 'Code\User\mcp.json' + +$SOURCES = @( + @{ Local = $primary; Prefix = 'workspace' } + @{ Local = $memDir; Prefix = 'memories' } +) +if (Test-Path $mcpJson) { $SOURCES += @{ Local = $mcpJson; Prefix = 'mcp-config' } } + +# Touched-folder log (companion to mark-touched.ps1) +$touchedLog = Join-Path $repoRoot 'state\agent-touched-folders.log' +if (Test-Path $touchedLog) { + Get-Content $touchedLog | Where-Object { $_ -and -not $_.StartsWith('#') } | ForEach-Object { + $line = ($_ -split '#',2)[0].Trim() + if ($line -and (Test-Path $line)) { + $prefix = ($line -replace '[:\\/ ]', '_').Trim('_').ToLower() + if ($prefix.Length -gt 60) { $prefix = $prefix.Substring($prefix.Length - 60) } + $SOURCES += @{ Local = $line; Prefix = "touched/$prefix" } + } + } +} + +# --- credentials --- +$SA = $cfg.vault.storageAccount +$container = $cfg.vault.draftContainer +$keyFile = Join-Path $repoRoot $cfg.vault.keyFile +if (-not (Test-Path $keyFile)) { Write-Error "vault-sync: key file missing: $keyFile"; exit 3 } +$KEY = (Get-Content $keyFile -Raw).Trim() -replace '^KEY=','' + +$expiry = (Get-Date).ToUniversalTime().AddHours(24).ToString('yyyy-MM-ddTHH:mm:ssZ') +$sas = az storage container generate-sas --account-name $SA --account-key $KEY --name $container ` + --permissions rwdlc --expiry $expiry --https-only -o tsv +if (-not $sas) { Write-Error "vault-sync: SAS generation failed"; exit 4 } + +# --- log --- +$logDir = Join-Path $repoRoot 'logs' +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } +$ts = Get-Date -Format 'yyyy-MM-dd_HHmmss' +$log = Join-Path $logDir "sync-$ts.log" + +$excludePatterns = '*.lock;*.pid;~$*;Thumbs.db;.DS_Store' +$totalErrors = 0 + +foreach ($src in $SOURCES) { + if (-not (Test-Path $src.Local)) { + "SKIP missing: $($src.Local)" | Tee-Object -FilePath $log -Append + continue + } + $remote = "https://$SA.blob.core.windows.net/$container/$($src.Prefix)?$sas" + $isFile = -not (Get-Item $src.Local).PSIsContainer + + if ($isFile) { + $azArgs = @('copy', $src.Local, $remote, '--overwrite=ifSourceNewer') + } else { + $azArgs = @('sync', $src.Local, $remote, '--recursive', '--exclude-pattern', $excludePatterns, '--delete-destination=false') + } + if ($DryRun) { $azArgs += '--dry-run' } + + "==== $($src.Prefix) <- $($src.Local) ====" | Tee-Object -FilePath $log -Append + & azcopy @azArgs 2>&1 | Tee-Object -FilePath $log -Append + if ($LASTEXITCODE -ne 0) { $totalErrors++ } +} + +"==== sync complete | sources=$($SOURCES.Count) | errors=$totalErrors | log=$log ====" | Tee-Object -FilePath $log -Append +exit $totalErrors diff --git a/agent-os/bootstrap.ps1 b/agent-os/bootstrap.ps1 new file mode 100644 index 0000000..fd96203 --- /dev/null +++ b/agent-os/bootstrap.ps1 @@ -0,0 +1,128 @@ +# @recall.works/agent-os | bootstrap.ps1 | v1.0 +# Windows installer. Idempotent. Re-run safely. +# +# 1. Verifies dependencies (PowerShell 7+, ollama, az, azcopy). +# 2. Verifies config.json exists (created from example if missing). +# 3. Creates state/ and logs/ directories. +# 4. Copies template files into the agent's memory dir (skips existing). +# 5. Self-tests spend-gate (fails the install if it can't pass). +# 6. Registers scheduled tasks per config.schedules. +# +# Usage: pwsh ./bootstrap.ps1 [-Config ./config.json] [-SkipTasks] [-WhatIf] + +[CmdletBinding()] +param( + [string] $Config = (Join-Path $PSScriptRoot 'config.json'), + [switch] $SkipTasks +) + +$ErrorActionPreference = 'Stop' +$repoRoot = $PSScriptRoot + +Write-Host '=== Recall · Agent OS bootstrap ===' -ForegroundColor Cyan + +# --- step 1: dependencies --- +function Need($name) { + $cmd = Get-Command $name -ErrorAction SilentlyContinue + if (-not $cmd) { Write-Error "missing dependency: $name (install it and re-run)"; exit 2 } + " ok $name -> $($cmd.Source)" +} +'checking dependencies...' +Need pwsh +Need ollama +Need az +Need azcopy + +# --- step 2: config --- +if (-not (Test-Path $Config)) { + $example = Join-Path $repoRoot 'config.example.json' + if (-not (Test-Path $example)) { Write-Error "config.example.json missing"; exit 3 } + Copy-Item $example $Config + Write-Host " created $Config (from example) — EDIT IT before continuing." -ForegroundColor Yellow + Write-Host ' re-run bootstrap.ps1 once the config is filled in.' -ForegroundColor Yellow + exit 0 +} +$cfg = Get-Content $Config -Raw | ConvertFrom-Json +" ok config: $Config" + +# --- step 3: directories --- +foreach ($d in @('state','logs','config')) { + $p = Join-Path $repoRoot $d + if (-not (Test-Path $p)) { New-Item -ItemType Directory -Path $p -Force | Out-Null } +} +" ok state/ logs/ config/" + +# --- step 4: copy templates into agent memory dir --- +$memDir = [System.Environment]::ExpandEnvironmentVariables($cfg.memory.memoriesDir) +if (-not (Test-Path $memDir)) { + Write-Host " warn memory dir does not exist yet: $memDir" -ForegroundColor Yellow + Write-Host " create it (or open the editor's chat once) and re-run, or pre-create:" -ForegroundColor Yellow + Write-Host " New-Item -ItemType Directory -Path '$memDir' -Force" -ForegroundColor Yellow +} else { + $tdir = Join-Path $repoRoot 'templates' + Get-ChildItem $tdir -File | ForEach-Object { + $dest = Join-Path $memDir ($_.Name -replace '\.tmpl$','') + if (-not (Test-Path $dest)) { + Copy-Item $_.FullName $dest + " copied template: $($_.Name) -> $dest" + } else { + " skip (exists): $dest" + } + } +} + +# --- step 5: spend-gate self-test --- +'self-testing spend-gate...' +& (Join-Path $repoRoot 'bin\spend-gate.ps1') -Config $Config -Quiet +if ($LASTEXITCODE -ne 0) { Write-Error " spend-gate failed (exit $LASTEXITCODE). Fix and re-run."; exit 4 } +" ok spend-gate" + +# --- step 6: scheduled tasks --- +if ($SkipTasks) { + "skipped scheduled task registration (-SkipTasks)" + Write-Host '=== bootstrap done ===' -ForegroundColor Cyan + exit 0 +} + +function Add-DailyTask([string]$name, [string]$script, [string]$cronTime) { + # cronTime like "0 2 * * *" -> hour 2 daily; we use a tiny parser + $parts = $cronTime.Split(' ') + $hour = [int]$parts[1]; $minute = [int]$parts[0] + $when = (Get-Date).Date.AddHours($hour).AddMinutes($minute) + $action = New-ScheduledTaskAction -Execute 'pwsh.exe' -Argument "-NoProfile -File `"$script`" -Config `"$Config`"" + $trigger = New-ScheduledTaskTrigger -Daily -At $when + $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 1) -MultipleInstances IgnoreNew + Register-ScheduledTask -TaskName $name -Action $action -Trigger $trigger -Settings $settings -Force | Out-Null + " task registered: $name @ $($when.ToString('HH:mm')) daily" +} +function Add-WeeklyTask([string]$name, [string]$script, [string]$cronTime) { + $parts = $cronTime.Split(' ') + $hour = [int]$parts[1]; $minute = [int]$parts[0] + $dow = $parts[4] # "0" = Sunday + $dowName = @('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')[[int]$dow] + $when = (Get-Date).Date.AddHours($hour).AddMinutes($minute) + $action = New-ScheduledTaskAction -Execute 'pwsh.exe' -Argument "-NoProfile -File `"$script`" -Config `"$Config`"" + $trigger = New-ScheduledTaskTrigger -Weekly -At $when -DaysOfWeek $dowName + $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 2) -MultipleInstances IgnoreNew + Register-ScheduledTask -TaskName $name -Action $action -Trigger $trigger -Settings $settings -Force | Out-Null + " task registered: $name @ $($dowName) $($when.ToString('HH:mm'))" +} +function Add-RepeatingTask([string]$name, [string]$script, [int]$minutes) { + $action = New-ScheduledTaskAction -Execute 'pwsh.exe' -Argument "-NoProfile -File `"$script`" -Config `"$Config`"" + $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(2) -RepetitionInterval (New-TimeSpan -Minutes $minutes) + $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 10) -MultipleInstances IgnoreNew + Register-ScheduledTask -TaskName $name -Action $action -Trigger $trigger -Settings $settings -Force | Out-Null + " task registered: $name every $minutes min" +} + +$bin = Join-Path $repoRoot 'bin' +Add-DailyTask 'Recall-VaultSync-Nightly' (Join-Path $bin 'vault-sync.ps1') $cfg.schedules.vaultSyncCron +Add-WeeklyTask 'Recall-VaultPromote-Weekly' (Join-Path $bin 'vault-promote.ps1') $cfg.schedules.vaultPromoteCron +Add-WeeklyTask 'Recall-BrainSnapshot-Weekly' (Join-Path $bin 'brain-snapshot.ps1') $cfg.schedules.brainSnapshotCron +Add-RepeatingTask 'Recall-RollingSummary-Q' (Join-Path $bin 'qwen-rolling-summary.ps1') $cfg.schedules.rollingSummaryEveryMinutes + +Write-Host '=== bootstrap done ===' -ForegroundColor Cyan +Write-Host 'Next:' +Write-Host ' 1. Verify config.json — workspaceId, storageAccount, etc.' +Write-Host ' 2. Run: pwsh ./bin/qwen-coldstart.ps1 -Config ./config.json -Save' +Write-Host ' 3. Read your editor''s memory dir to confirm templates landed.' diff --git a/agent-os/brain/Dockerfile b/agent-os/brain/Dockerfile new file mode 100644 index 0000000..effed25 --- /dev/null +++ b/agent-os/brain/Dockerfile @@ -0,0 +1,37 @@ +# Recall Brain — reference Dockerfile (blueprint) +# v0.2 target. Today this builds the dependency layer; the actual +# recall.py service is a stub that returns 501 on every endpoint +# until the v0.2 source drop. + +FROM python:3.12-slim + +ENV PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + RECALL_DATA=/data \ + RECALL_PORT=8080 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + git curl ca-certificates build-essential \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Pinning these is intentional — embedding model + chromadb wire format +# must move together or the persistent store breaks across upgrades. +RUN pip install --no-cache-dir \ + chromadb==0.5.5 \ + fastapi==0.115.0 \ + "uvicorn[standard]==0.30.6" \ + sentence-transformers==3.0.1 \ + pydantic==2.9.2 \ + sse-starlette==2.1.3 + +COPY recall.py /app/recall.py + +VOLUME ["/data"] +EXPOSE 8080 + +# When v0.2 drops, this becomes: +# CMD ["uvicorn", "recall:app", "--host", "0.0.0.0", "--port", "8080"] +# Until then, the stub serves /health only and 501s the rest. +CMD ["python", "/app/recall.py"] diff --git a/agent-os/brain/README.md b/agent-os/brain/README.md new file mode 100644 index 0000000..9927403 --- /dev/null +++ b/agent-os/brain/README.md @@ -0,0 +1,81 @@ +# Recall · Networked Brain + +A small HTTP+SSE service wrapping ChromaDB. Multiple agents (multiple +machines, multiple users) can share recall, remember, reflect, checkpoint +primitives over the wire. + +This is **v0.2 territory** — the current published files are a blueprint, not +a one-click build. The pattern below is verified in production at the +originating workstation (call it ``); the public packaging +is being de-personalized. + +## What's in this folder + +- `Dockerfile` — base image: `python:3.12-slim`, installs `chromadb`, + `fastapi`, `uvicorn`, `sentence-transformers`. ~1.2 GB final. +- `docker-compose.yml` — one-service compose with a named volume for the + vector store, port 8080 exposed. +- `recall.py` — HTTP+SSE service. Implements 16 tools (recall, remember, + reflect, checkpoint, anti_pattern, forget, index_file, reindex, + memory_stats, pulse, session_close, etc.). +- `agency_sidecar_patch.md` — design note explaining why a frozen + prebuilt-index ChromaDB collection plus a writable sidecar collection + in the SAME persistent client is the right pattern when you want to + ship sealed reference content alongside per-tenant scratch space. + +## The pattern that matters + +The reference architecture is **frozen-read + sidecar-write + merge on query.** + +- One ChromaDB collection ships with the image, sealed (HNSW segment + read-only). It contains your foundation corpus — RFCs, agency docs, + internal references. It never changes. +- A second ChromaDB collection is created lazily in the same persistent + client. It accepts writes. It holds session memory, anti-patterns, + user-specific reflections. +- `recall()` queries both, merges by distance, returns the top-N. +- Backup → only the writable sidecar needs snapshotting (the frozen + collection regenerates from image rebuild). + +That's it. The HTTP shell on top of it is mechanical. + +## What's NOT here yet + +- Full `recall.py` source, de-personalized. Coming with the v0.2 image. +- `agency_loader.py` — script for loading new corpus into the writable + sidecar via stable IDs (`sha256(collection:path)[:16]`). +- Multi-tenant auth (currently the originating implementation uses a + single shared `X-API-Key` header per machine; SaaS-grade auth is + deliberately deferred). +- Coordination primitives (`claim` / `release` / `who_has` / `handoff`). + Designed but not yet open-sourced; v0.3. + +## Why this is in v0.2 not v0.1 + +The whitepaper (`site/agent-os.html`) describes the architecture. The +pattern is the deliverable. A working reference image is a quality-of-life +add-on. Ship the spec, then the impl. This avoids the trap where the public +release is a one-machine-only artifact. + +If you want to build it yourself today, this is enough: + +```bash +pip install chromadb fastapi uvicorn[standard] sentence-transformers +# Implement the 16 tools listed above as FastAPI endpoints, each +# delegating to one of two ChromaDB collections (frozen + sidecar) +# in a single PersistentClient. +# Wire SSE for the streaming endpoints (recall, reflect). +# Mount /data as a docker volume. +``` + +The originating implementation runs at ~50 chunks/sec on a single 5080-class +GPU embedder, ~5 MB RAM idle, ~1.5 GB with the foundation corpus loaded. + +## Reference + +The originating brain is part of an internal project named "IceWhisperer" in +the originating workstation. The architecture note that documents the +frozen-read + writable-sidecar trick lives in +`reference/icewhisperer/icewhisperer-brain-architecture.md` of that project's +memory dir. It will be re-published here as `agency_sidecar_patch.md` once +de-personalized. diff --git a/agent-os/brain/agency_sidecar_patch.md b/agent-os/brain/agency_sidecar_patch.md new file mode 100644 index 0000000..de36908 --- /dev/null +++ b/agent-os/brain/agency_sidecar_patch.md @@ -0,0 +1,55 @@ +# Agency Sidecar Pattern + +When you want to ship a brain image with frozen reference content +(an "agency corpus" — RFCs, agency docs, regulatory text, internal +references) AND let downstream users add their own writable memory +on top, the right shape is **two ChromaDB collections in one +persistent client.** + +## The problem + +Ship a docker image with a pre-built ChromaDB collection that contains +your foundation corpus. The HNSW segment in that collection is sealed +read-only at image build time (good — index is fast, well-tuned). But +that means every `add()` against that collection silently no-ops: +the call returns success, `count()` never grows. Surprising. + +## The fix + +In the same `PersistentClient`, lazily create a SECOND collection. +Call it `_agency` or `_user`. It is fresh, has a writable +HNSW segment, and accepts writes normally. + +In `recall()`, query BOTH collections, merge results by distance, +return top-N to the caller. The user can't tell the difference. + +In `remember()`, only ever write to the sidecar. + +In `forget()`, only operate on the sidecar (you cannot delete from +the frozen collection regardless). + +## Why two collections instead of one writable collection + +Because the frozen one is gigabytes (foundation corpus is the +expensive bit) and you do not want to rebuild it on every backup +cycle. With this pattern, `brain-snapshot.ps1` only zips the sidecar +(+ collection-metadata SQLite) — typically a few hundred MB +regardless of how big the foundation is. + +## Naming and stable IDs + +Use stable document IDs derived from a content hash so re-indexing is +idempotent: + +```python +doc_id = sha256(f"{collection_name}:{path}".encode()).hexdigest()[:16] +``` + +The 16-hex prefix is plenty unique for a per-collection corpus and +keeps the IDs short in logs. + +## What about Qdrant / Weaviate / Vespa + +Same shape. Two collections / classes / namespaces. Frozen + sidecar. +Merge in the read path. The cost discipline (only back up the +sidecar) is the same. diff --git a/agent-os/brain/docker-compose.yml b/agent-os/brain/docker-compose.yml new file mode 100644 index 0000000..78b53ea --- /dev/null +++ b/agent-os/brain/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.9" + +# Recall · Networked Brain — single-host compose +# +# Brings up the brain service on http://localhost:8080. Persistent vector +# store lives in the named volume `recall-data` so container restarts don't +# wipe state. To back it up, run bin/brain-snapshot.ps1 (it points at the +# resolved volume mount path on disk). +# +# For multi-machine: put this behind your reverse proxy of choice (Caddy, +# Traefik, an Azure Container App with ingress) and front it with mTLS or a +# shared X-API-Key header. The originating implementation uses a single +# shared API key per machine — SaaS-grade auth is deferred to v0.3. + +services: + brain: + build: . + image: recall.works/brain:v0.2 + container_name: recall-brain + ports: + - "8080:8080" + environment: + - RECALL_PORT=8080 + - RECALL_DATA=/data + # - RECALL_API_KEY=set-me-in-.env + volumes: + - recall-data:/data + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"] + interval: 30s + timeout: 5s + retries: 5 + +volumes: + recall-data: diff --git a/agent-os/brain/recall.py b/agent-os/brain/recall.py new file mode 100644 index 0000000..1d0de29 --- /dev/null +++ b/agent-os/brain/recall.py @@ -0,0 +1,46 @@ +""" +recall.py — Recall · Networked Brain (stub for v0.1, full impl in v0.2) + +This file is intentionally a thin stub. The architecture is documented in +brain/README.md. A working reference implementation will land here in v0.2. + +Until then, this stub: + - boots a FastAPI app + - serves GET /health -> 200 {ok: true, version: "0.1-stub"} + - returns 501 NotImplemented on every other endpoint + +You can build the docker image today (`docker compose up --build`) to verify +the dependency layer pins compile cleanly on your platform. The data volume +will sit empty until the v0.2 service code is wired in. +""" + +import os +from fastapi import FastAPI, HTTPException + +VERSION = "0.1-stub" +DATA_DIR = os.environ.get("RECALL_DATA", "/data") +PORT = int(os.environ.get("RECALL_PORT", "8080")) + +app = FastAPI(title="Recall Brain", version=VERSION) + + +@app.get("/health") +def health(): + return {"ok": True, "version": VERSION, "data_dir": DATA_DIR} + + +@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) +def not_implemented(path: str): + raise HTTPException( + status_code=501, + detail=( + f"recall.py is a v0.1 stub. /{path} is part of the v0.2 spec and " + "is not yet implemented. See brain/README.md for the design and " + "the architecture note. Pull requests welcome." + ), + ) + + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=PORT) diff --git a/agent-os/config.example.json b/agent-os/config.example.json new file mode 100644 index 0000000..eb2729b --- /dev/null +++ b/agent-os/config.example.json @@ -0,0 +1,58 @@ +{ + "_comment": "Copy this file to config.json and edit. config.json is gitignored.", + "_brand": "Recall :: Agent OS reference implementation config", + + "workspace": { + "primary": "C:\\Dev", + "secondary": "D:\\Dev", + "_note": "Primary is the active code root. Secondary is for archive / separate-product surfaces." + }, + + "memory": { + "memoriesDir": "%APPDATA%\\Code\\User\\globalStorage\\github.copilot-chat\\memory-tool\\memories", + "transcriptsDir":"%APPDATA%\\Code\\User\\workspaceStorage\\\\GitHub.copilot-chat\\transcripts", + "workspaceId": "REPLACE_WITH_YOUR_VS_CODE_WORKSPACE_ID", + "_note": "Path conventions match GitHub Copilot Chat's memory tool. Other editors will differ." + }, + + "vault": { + "provider": "azure-blob", + "storageAccount": "REPLACE_WITH_YOUR_STORAGE_ACCOUNT", + "draftContainer": "draft", + "vaultContainer": "vault", + "wormDays": 2557, + "lifecycleDraftDays":7, + "lifecycleVaultDays":30, + "keyFile": "config\\.vault-key.txt", + "_note": "vaultContainer should have time-based immutability set (Azure Blob) or equivalent WORM policy." + }, + + "spendGate": { + "monthlyCeilingUSD": 25, + "cacheSeconds": 60, + "failClosed": true, + "killSwitchFile": "config\\.vault-killswitch", + "_note": "Every billable script must clear killswitch + this gate + provider-side budget alert." + }, + + "localModel": { + "runtime": "ollama", + "model": "qwen2.5-coder:14b", + "fallbackModel": "qwen2.5:7b", + "killSwitchFile": "config\\.qwen-killswitch", + "_note": "Used for cold-start briefs, rolling summaries, and verbose-memory compression." + }, + + "schedules": { + "vaultSyncCron": "0 2 * * *", + "vaultPromoteCron": "0 3 * * 0", + "brainSnapshotCron": "0 4 * * 0", + "rollingSummaryEveryMinutes": 15, + "_note": "bootstrap.ps1 translates these into Windows scheduled tasks." + }, + + "branding": { + "agentSignature": "agent-NNNN", + "_note": "Pick a unique short hex/codename per Rule 9. Used in file-edit stamps." + } +} diff --git a/agent-os/docs/QUICKSTART.md b/agent-os/docs/QUICKSTART.md new file mode 100644 index 0000000..6cc393b --- /dev/null +++ b/agent-os/docs/QUICKSTART.md @@ -0,0 +1,95 @@ +# Quickstart + +## Prereqs + +- **PowerShell 7+** (cross-platform). +- **ollama** with at least one local model pulled (default: `qwen2.5-coder:14b`). +- **Azure CLI** (`az`) + **azcopy** if you're using the reference Azure Blob + vault. If you're rolling your own object-storage backend, you can skip these + and adapt `bin/vault-sync.ps1` accordingly. +- A coding agent host whose memory directory you control (e.g. GitHub Copilot + Chat under VS Code; the path is in `config.example.json`). + +## 60-second install + +```powershell +git clone https://github.com/recall-works/agent-os +cd agent-os +cp config.example.json config.json +# 1) edit config.json — fill in workspaceId + storageAccount at minimum +# 2) put your storage key into config/.vault-key.txt as: KEY= +.\bootstrap.ps1 +``` + +`bootstrap.ps1` is idempotent. First run creates `config.json` from the +example and stops so you can edit. Second run does the real work. + +## What just happened + +- `state/` and `logs/` directories created at the repo root. +- Templates from `templates/` copied into your agent's memory directory + (skipped if files already exist there — destructive overwrites do not happen). +- `spend-gate.ps1` self-test ran (verifies your provider auth + cost API access). +- Scheduled tasks registered: + - `Recall-VaultSync-Nightly` — daily 2 AM + - `Recall-VaultPromote-Weekly` — weekly Sunday 3 AM + - `Recall-BrainSnapshot-Weekly` — weekly Sunday 4 AM + - `Recall-RollingSummary-Q` — every 15 min, idempotent on transcript growth + +## First-day usage + +After bootstrap, your day-to-day workflow is the agent's, not yours. The +scheduled tasks run on their own. The memory dir templates feed the agent +durable context every conversation. + +If you want to verify, manually: + +```powershell +pwsh ./bin/vault-sync.ps1 -DryRun +pwsh ./bin/qwen-coldstart.ps1 -Save +``` + +The first dry-runs the nightly snapshot (no data written). The second +generates `_coldstart-brief.md` in your memory dir — open the agent and +ask it to summarize the brief; you'll see it react to durable context. + +## Verification checklist + +- [ ] `config.json` exists and is **not** committed (it's gitignored). +- [ ] `config/.vault-key.txt` exists, contains `KEY=`, **not** committed. +- [ ] Memory dir contains `00-routing.md`, `05-audit-trail.md` etc. +- [ ] `state/.spend-gate-last` was written by the self-test. +- [ ] Scheduled tasks visible in Task Scheduler under names starting with `Recall-`. + +## Cost expectation + +Per the whitepaper (`/site/agent-os.html`), all-in monthly cost for a single +workstation running this stack: **under $1/mo** in the reference Azure Blob +vault tier. The local model is free. Your bandwidth is whatever the nightly +snapshot pulls (typically 50-200 MB after the first full sync). + +## When to read what + +- Stuck on something? Read `templates/fix-at-root-reflex.md.tmpl` — it's the + habit that pays the highest dividends. +- Adding a new external folder to backups? Use `bin/mark-touched.ps1`. +- Brain went sideways? Read `brain/README.md` and the + `agency_sidecar_patch.md` design note. + +## Uninstall + +```powershell +# Remove scheduled tasks +Get-ScheduledTask -TaskName 'Recall-*' | Unregister-ScheduledTask -Confirm:$false + +# Remove repo +Remove-Item -Recurse -Force + +# Vault data (if you want to fully clean up) +# - draft container: free to delete +# - vault container: time-locked WORM, you cannot delete until lock expires +# - sealed local backups under state/sealed-brain-backups/: rename .SEALED.zip -> .zip first +``` + +The vault container's WORM policy is the only thing the uninstall **can't** +clean up immediately, by design. That's the point of the policy. diff --git a/agent-os/install.sh b/agent-os/install.sh new file mode 100644 index 0000000..80aff94 --- /dev/null +++ b/agent-os/install.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# @recall.works/agent-os | install.sh | v0.1 (placeholder) +# +# A bash equivalent of bootstrap.ps1 is on the v0.2 roadmap. Today this +# script verifies dependencies and prints the manual steps. +# +# Usage: ./install.sh +# +# The PowerShell scripts in bin/ run on PowerShell 7+ (cross-platform), so +# you can use them directly on Linux/macOS today — install pwsh, ollama, az, +# azcopy, then `pwsh ./bootstrap.ps1`. A native bash variant is coming. + +set -euo pipefail + +echo "=== Recall · Agent OS install (bash placeholder) ===" + +need() { + if ! command -v "$1" >/dev/null 2>&1; then + echo " MISSING: $1 (install via your package manager and re-run)" + return 1 + fi + echo " ok $1 -> $(command -v "$1")" +} + +missing=0 +need pwsh || missing=$((missing+1)) +need ollama || missing=$((missing+1)) +need az || missing=$((missing+1)) +need azcopy || missing=$((missing+1)) + +if [ "$missing" -gt 0 ]; then + echo + echo "Install the missing items above, then re-run." + exit 2 +fi + +echo +echo "All dependencies present. PowerShell 7 will drive the rest:" +echo " pwsh ./bootstrap.ps1" +echo +echo "(A native bash bootstrap is on the v0.2 roadmap — same logic, no pwsh needed.)" diff --git a/agent-os/templates/00-routing.md.tmpl b/agent-os/templates/00-routing.md.tmpl new file mode 100644 index 0000000..2fe246a --- /dev/null +++ b/agent-os/templates/00-routing.md.tmpl @@ -0,0 +1,38 @@ +# 00-routing.md — what to load, when + +This is the entry point your agent reads at the start of every conversation. +It is intentionally short. Anything longer than ~200 lines belongs in a +reference file under `/memories/reference//`. + +## Triggers + +When the user mentions the keywords below, the agent loads the indicated files +BEFORE responding to anything else. + +| Trigger phrase | Load | +|---------------------------|----------------------------------------------------------| +| `` | `tree-profile.md`, `01-preflight.md`, `03-preferences.md` | +| `rule:` / `vision:` (first word) | Append the line to `vision.md` and brain BEFORE replying | +| (any other trigger) | (your conventions here) | + +## Cold-start protocol + +1. Read this file. +2. Read `01-preflight.md` for any per-machine setup checks. +3. Read `05-audit-trail.md` and pull the last 5-8 OPEN sessions. +4. Run `bin/qwen-coldstart.ps1 -Save` to generate `_coldstart-brief.md` + from current memory + newest revival doc. +5. Read `_coldstart-brief.md`. +6. (Optional) Pulse the brain: `recall("last session context")`. + +## Memory layout + +- `/memories/*.md` — ACTIVE. Top of context every turn. Keep tight. +- `/memories/session/*.md` — current chat scratch. +- `/memories/reference/*.md` — listed but not auto-loaded; read on demand. +- `/memories/archive/*.md` — cold storage (compressed audit-trail rows, closed sessions). + +## Address conventions + +Replace this line with how the user wants to be addressed. +e.g. "Always address user as ``. Never ``." diff --git a/agent-os/templates/REVIVAL-template.md b/agent-os/templates/REVIVAL-template.md new file mode 100644 index 0000000..f37a812 --- /dev/null +++ b/agent-os/templates/REVIVAL-template.md @@ -0,0 +1,55 @@ +# REVIVAL-S-.md + +> Drop a copy of this template into your repo at `REVIVAL-S-.md` +> and fill it in as the session progresses. The cold-start protocol reads +> the newest revival doc on every fresh session. + +## Status + +`OPEN | CLOSED | BLOCKED`. One line. + +## What we set out to do + +One paragraph. The goal as stated by the user, verbatim where possible. + +## What got done + +- Bullet +- Bullet +- Bullet + +Cite file paths, version numbers, exact identifiers. Avoid prose-only summaries. + +## What's UNTESTED (R7) + +The single most important section. List every claim made above that was not +end-to-end verified. The next agent reads this first. + +- Untested 1 +- Untested 2 + +## Blockers + +- What's stuck and why. + +## Next concrete step + +1. ... +2. ... + +## Files touched + +- `path/to/file1` +- `path/to/file2` + +## How to resume + +A paragraph telling the next agent what to read first, what command to run +first, what the first 5 minutes of the next session should look like. + +## Brand stamp + +Per the project's brand-stamp rule, every file edited this session has a +header line like: + +`` diff --git a/agent-os/templates/audit-trail.md.tmpl b/agent-os/templates/audit-trail.md.tmpl new file mode 100644 index 0000000..91e164b --- /dev/null +++ b/agent-os/templates/audit-trail.md.tmpl @@ -0,0 +1,34 @@ +# 05-audit-trail.md — durable session log + +Each row of the table below is one session. The row is written when a session +closes or hits a meaningful checkpoint. Format is intentionally rigid so that +`bin/qwen-coldstart.ps1` can parse it without ambiguity. + +## Format + +`| S-id | STATUS | agent. one-line summary. |` + +- **S-id**: `S-YYYYMMDD-` (e.g. `S-20260507-vault-fullscope`). +- **STATUS**: one of `OPEN`, `CLOSED`, `BLOCKED`, `SUPERSEDED`, `LOCKED`. +- **agent**: short hex codename (e.g. `agent-a3f7`) so multiple agents on + multiple machines stay distinguishable in shared logs. +- **summary**: one paragraph. Telegraphese is fine. Preserve exact paths, + version numbers, hex IDs, file names. End with what was UNTESTED. + +Full detail per session lives in `REVIVAL-S-*.md` on disk and (if you have +a brain) under brain tag ``. + +## Compaction + +Once `05-audit-trail.md` exceeds ~30k tokens of loaded context, compress +verbose rows into `archive/closed-sessions-archive.md` and replace with +one-line stubs. `bin/latest-revival.ps1` is the inverse — it expands a single +revival doc back into prose on demand. + +--- + +# Audit Trail — Active Sessions + +| S-id | STATUS | agent. one-line summary. | +|------|--------|--------------------------| +| (your first row goes here) | OPEN | agent-NNNN. one-paragraph summary ending with what was UNTESTED. | diff --git a/agent-os/templates/fix-at-root-reflex.md.tmpl b/agent-os/templates/fix-at-root-reflex.md.tmpl new file mode 100644 index 0000000..5245168 --- /dev/null +++ b/agent-os/templates/fix-at-root-reflex.md.tmpl @@ -0,0 +1,46 @@ +# Fix-at-root reflex + +**When something fails the same way twice, stop fixing the symptom.** + +The fix-at-root reflex is the single most expensive habit to teach an AI +agent and the single most valuable one to keep. It is the difference between +"I patched the latest manifestation" and "the next manifestation can't happen." + +## The pattern + +1. **Notice repetition.** "I'm doing this again" / "this looks like last time" + / "I just fixed something like this two days ago." +2. **Stop the patch.** Do not write the next conditional or workaround. +3. **Name the root.** Write one sentence describing the underlying cause, + not the surface failure. If you can't, that means you don't know yet. +4. **Decide the right level.** Code fix? Config fix? Convention fix? + Documentation fix? Architectural fix? Pick the level the cause actually + lives at — usually higher than the level you noticed it. +5. **Make the fix at that level.** Even if it's slower today. +6. **Record it.** REVIVAL doc, audit-trail row, anti-pattern note. Future + sessions need to know this happened so the lesson compounds. + +## Examples (from the originating workspace) + +- Surface: "ollama returns empty body." + Patch: retry with smaller prompt. + Root: ollama silently truncates >32K context. + Fix: cap input at the call site once, document the limit. Cite next time. + +- Surface: "agents keep writing files into `C:\Users\...`" + Patch: ad-hoc warning in each session. + Root: the rule said "never" but operational reality required exact-path + carve-outs (memory tool, transcripts dir). + Fix: rewrite the rule to match reality so it stops getting ignored. + +- Surface: "qwen refused — 'don't have access to file system'." + Patch: try a different prompt. + Root: input was raw jsonl (mostly tool plumbing JSON), no prose visible. + Fix: pre-extract `user.message.content` + `assistant.message.content` + server-side before calling qwen. + +## What to do when the agent slips + +If you (the agent reading this) catch yourself patching the same thing twice, +write `FIX-AT-ROOT:` followed by a one-sentence root description and stop. +Then think about the right level. diff --git a/site/CNAME b/site/CNAME new file mode 100644 index 0000000..8cf14f6 --- /dev/null +++ b/site/CNAME @@ -0,0 +1 @@ +www.recall.works \ No newline at end of file diff --git a/site/architecture.html b/site/architecture.html new file mode 100644 index 0000000..40f3818 --- /dev/null +++ b/site/architecture.html @@ -0,0 +1,235 @@ + + + + + + +Architecture · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

Architecture at a glance

+
+ +
+
Hot context
+
+
+
User memory
+
Auto-loaded every turn. Routing rules, preferences, audit-trail tail.
+ /memories/*.md +
+
+
Session memory
+
Per-conversation scratch. Cleared on close.
+ /memories/session/ +
+
+
Repo memory
+
Codebase facts. Append-only, verified at write time.
+ /memories/repo/ +
+
+
+ +
+
Warm context
+
+
+
Reference memory
+
Loaded on routing trigger. Topic-scoped per project area. Listed but not auto-included.
+ /memories/reference/ +
+
+
Semantic brain
+
Tens of thousands of chunks. Fuzzy recall across SDKs, documentation, prior work, and decisions.
+ vector store · cloud-hosted +
+
+
Cold-start brief
+
Local-model-distilled ~3KB summary of state files + last N audit rows + newest session journal.
+ coldstart distiller +
+
+
+ +
+
Cold storage
+
+
+
Draft container
+
Mutable working backup. 30-day soft-delete window. Versioning + change feed.
+ object storage · Cool tier +
+
+
Vault container
+
WORM-immutable 7yr. Snapshots, one-time promotes. Lifecycle to Archive at 30d.
+ object storage · Archive tier +
+
+
Sealed local
+
.SEALED.zip with DO-NOT-READ.txt sentinel + .gitignore. Agent searches skip it.
+ _sealed-brain-backups/ +
+
+
+ +
+
Guardrails
+
+
+
Kill switch
+
Touch a sentinel file. All billable scripts abort exit 99 until removed.
+ .qwen-killswitch +
+
+
Spend gate
+
Checks cloud month-to-date spend vs ceiling before any billable op. Fail-closed.
+ spend-gate.ps1 +
+
+
Cloud budget
+
Email alerts at 50% / 75% / 100% actual + 100% forecasted. Outside-in safety net.
+ provider budgets API +
+
+
+ +
+
Discipline
+
+
+
Audit-trail
+
Every session writes one row. Open / closed / locked status. Survives all compaction.
+ audit-trail.md +
+
+
Session journals
+
Per-session detail dossier. Concrete, dense, restorable. Archived when stale.
+ REVIVAL-*.md +
+
+
Fix-at-root reflex
+
Encoded rule: notice bug in shared infra → fix source first, never route around.
+ fix-at-root-reflex.md +
+
+
+ +
+
+ +
+

Scaling beyond one workstation: the networked brain

+

The pattern starts on a single workstation, but the semantic-brain pillar is designed to network. Run the brain as a containerized service exposing HTTP and Server-Sent Events, and any number of agents on any number of machines hit the same recall surface — no per-seat duplication of the corpus, no drift between team members, no re-embedding when a new agent joins.

+
+
+
Brain service
+
+
+
Frozen read collection
+
Curated corpus baked into the image at build time. Sealed vector segment, fast queries, deterministic across deploys. Restart-safe.
+ prebuilt-index/ in container +
+
+
Sidecar write collection
+
Lazily created at first write in the same persistent client. Holds new memories, ad-hoc corpus loads, per-agent remember() calls. Always writable.
+ side-collection · same DB file +
+
+
Merge at query time
+
Each recall() queries both collections in parallel, merges by distance, returns top-N. Caller never sees the seam.
+ recall.py merge layer +
+
+
+
+
Multi-agent
+
+
+
Shared HTTP/SSE
+
Multiple agents — same model or different — connect to one brain URL. Every remember by one agent is queryable by every other within seconds.
+ /sse · /tool/recall · /tool/remember +
+
+
Coordination primitives
+
Optional layer adds claim() / release() / handoff() / pulse_others() so agents don't step on each other on a shared task.
+ multi-agent coord wedge +
+
+
Audit-trail still wins
+
Even with a shared brain, the canonical decision log is the per-repo audit-trail. Brain is for fuzzy recall; audit-trail is for ground truth.
+ audit-trail.md (per workspace) +
+
+
+
+

This is how the same architecture scales from "one developer, one machine, one Copilot" to "a team of humans + agents working a multi-month codebase together" without redesigning anything below the brain layer.

+
+ +
+

How a session actually runs

+
+
    +
  1. Trigger. User types a routing keyword. Agent loads scoped memory, runs brain pulse, fetches latest revival doc.
  2. +
  3. Work. Edits, searches, runs commands, calls scripts. Branding stamp + version bump on every touched file.
  4. +
  5. Checkpoint. Every ~5 exchanges, brain checkpoint. Discoveries written to durable memory immediately, not "noted for later."
  6. +
  7. Touched-folder log. Anything outside the workspace gets registered so the next backup grabs it.
  8. +
  9. Close. Audit-trail row + REVIVAL doc + brain remember(). Session memory archived.
  10. +
  11. Overnight. Scheduled tasks run vault sync, weekly brain snapshot, and rolling-window memory archive — all gated by spend-gate.
  12. +
+
+
+ + + +
+ + diff --git a/site/assets/og-card.png b/site/assets/og-card.png new file mode 100644 index 0000000000000000000000000000000000000000..0e77b04e80b293a3db6d167eda2c5d0e72b61672 GIT binary patch literal 187826 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%0A5)CftPyErI$2(8Lrnwc})+wnH(+15q5*SiA^u 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 zΞ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≧*OGx&Kj#p%3#@cGQ55v*@12V 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

II4f0=v4}v8(NADjKh+1Spb|KkQ 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 z z+rH)Q-vF?M;fy$!T*4B2^)d%H_DTKS!QzhsAX?~CQl)IQ65njtqbK`+eu<%Fb3QJe zuHz&@v4&RLOwBr)mCj4mS9ff#SitrJU4R# z9>p7L38im`eRQUry{$(omFVs(bdq)MbnE1I);^^mq2LA~yOcvxH)9}>B)U(L$E5P3 z`{D#jA-QPHktBr6OVY9WOFr|1OsxXsGgSzU&kzFxI9&aKz?_~L?4DM~D1wJ78Ep~E zU(d?hx$Jv?1D32832L39?MaM)he{+#F6W!1KwCt^axzz&UJWjOO_D|ZWfJz9l5T+( z^`4N<$R$2e;!eg>ZVLxr_WPV23VmGjl@r$#X3H#ZLw$ILaD#B)`U7IOS@|AfNDE~w z*%pghbvmV}(18W^tm4mpl_{eM1@lH}#q#zt6zD(Ah#=n=cjwXt%ucA6wK9*|RM$4Z zP*H`tok@xc_7$zTO7}Q;n~sGNcR`N>snP?$1a-^z>Ape2IZTFxBSnvqK|E9ZR9ei@ z_{pd{K9Qwt6dai}W z2QgVV>3wg6-9#JT@m}w$P17eH%j~n6ox~%{#xEw(li-xXgPP3`(WGZ$8)f1qiKQ*E z2sz=}sI3=uiRuRZ34KPmT)h$b^Ci!pBT9^&ZeA(04THL+$MGx~4>*14|HHP^Dem1_ zXTMfkewZR;Gf0n}Vj}=df-bg2(KP1%{ek)FTxbk0`p;mvjMjsFE|$O2p-Zj^&0J*I z7tZ6Mw&`)6;`hZTq3U>Yby$6GWpHvMn&zG2y@btN3@C!cpl<}6irq4^QV5e&=%?L+ ze~E?j``L;uwy1D;*<^mK76RbQ)j=N7Jj6&p4#l$dJ!8;-KKlqT4!grhwA(rfJ63dS zWL|44xU8+rw(OXXZv-pJOFO58y{P8av0;{g`&GvO~cQ$%si_Ot=uFCVZ-)L(D!uTTGtx7K;?r57xfPH-T z@60|8wLq0#p;Uu)EVSm{dn(Kr@C(1CGP9`b@ide6tygD>(+&TSPkhwDaNQ-Ey@R3@ zzE`z6E^EH zU4)}%W#cxqtk?z&;N`Mb_SWiB{UE&%-|l~i19z~khy^7{_A*#v$Aly-INcfCG|Z!(z>X`_m(9j>Xzi74>zv_FA(87*3VnAyk?N^k!f{4$K&v zfQ4qHTeG@?&A~$vwE(Hk`I)vgSC1OeSu^VjS^49)-!R1y`=W+*~vZhc;KJDtvp(2&dgT)sXE1rk&=z(Ugm>eX&!bl=lUucLM~hm7YAzuP-<_Wbu4vfVJ$ws z;=xko5luG&tp4(dlnjT+FBvkD4K< zB4$(|ovTwMZ|%+B93avcPAD~5AQ2~cTfnYp`bcMRo&0r+WUGunn6 zaQKRj{!{^Iwdt)zob8`G?vKfQ-^5SDVZkF^e#BH+fVu&jhjrVutX3L_{7(^()pB%G zIlS0c>AXZ~_bp8q(feTl0JVvm|N2DZuR_l#kT!Lt1lO)Qz(0Mcy#q^E>L)cZfkV8Y zxW_n2b|K9C+~JekJogr#FL(11eD5JTwc0c#0QOlg!>*O3JI9rF;lNWoF<3>1!Q~Wb zDGn^Bg?lgF0UX``p#tzWE`0iowh}kk+eT=k%uEDOML~|W6tZVLQ~swA@J_P8`1F8( z-|Po|yAP~Scawb+fci6KJLrADGgQnYfQ1R+>+pu$?vD5)f#|$*Hb1PJ=%D5%f)(sK z?kMwG>-J6D;x#y?;?!8Om~OvdG;V&2f;-j?s;Z-QfY_&)zO{s&YXeE~NQu+DOy6SO z)e!Rh>fA+3Qf9fcsoen)i(Tk2Ye1>5(QNmTg9ajS1qfmIoQ2<&2zh%HdO>jWOQ{BJ ze1{e6jotY3`hIv-KmOKMYII>-T(ls|lqwm(o>r{L0fs_z%G{&GPVuF1i+N)`mhDM> zzh?!t+6YAhy!|E9buvl0F&_vN5J?PIw?TzV&N%30? z`EyZ2RUqJK;7ZVrGCY6KL$Mw>(sje947idxSc{KBwMjkNh;=7SH`%Z55*4~EeyKH? z@NX{wR5Ij?nTJ8Msb!CBQz-BhUGQ(KSgojdNR&+XD@f4)PahOXO@!2xGoK!jx2@ej zpS!sR?g!3qjzn2Tg*?mosCJ={f7=LNEx=!PkAL3t-}S-yYS+e;e8mR|;D1R3-!eG& zPIyu`8-DjT4=0ZT&wB@Z6Px}!jPsu)RQmVnuE{V#JIn?Pj~U_|4&`qA)e6obXSw%Q z#iPsf%??8pPOXFP)}j;s{Qle)G&gVwz@>MlHaHx96GwKI&%B$^6L3FU zU1In(6r6{jgw>RpTn{7eg7akD(5-w!d*x9X+To7YC{4^J0F1Yu^60~5nQ%HIs>5Mr zr80YuZ^mz2EABa8w_Oh3DjDT^fbejQ;k)=B0r8Z~l3RFr_a?X!9r6KoElM1zLB~13 zm`D?SR=oNF!wz)GY{UI)lF3(#14F0&Rksg6jpjqi^x05#6><>6*lMM1_-nVePcKsb zRwIa%C`-ShPKM3;t>RGMP5_n8w69b5^7KUmQ4Or9$P{SY_xlX|s`WjHzTcC%*3W>A`6)m;7af|~0_4M^3k{d{*4YSrz-ADAuyRiuT3m3QUSc8q&>BAY-!%l1 ziV`#=*4qCyVEcwAglh8jza<1MA1yem>Edk+hGYIFJe?Bz*E0|g)M;EgpGC+spHB=& z*@TM!HajnF2T=F6?0XG$=|PAB_y(YauHzCMum4|X0Zr3VAHzY-y%)1Xm5gYaAy!zR$`Bp(crT!O3;kqyn#UgbgTwHxkX6KlF+J@-Y9aA?hRZo_n6J zkj3@sDWP8I(k*P`psL>r9!GbAsxoMmJaa(#a(c+0{}B>b%*N$<7Yqts*mb{t`!=rD z-P2P@4j`D`(d=TIUmhL$`phXdk@Q+m=t`IICFk!?Zb3(GK;6ExE%HpgigF!q6Npl5 zsh?@5}csQvLczx(L*1p-50{~nP# zd9kwMe~}O}(brC|;f#U(e{Q7Uno`4rw1Q8agj=VcBvV-g9ayx#D5&&$v_#cMtNEMk zcU1ziM}R^BmCDW0)gR9Ec#8WiH1m|N7Nfv%v)jVwDF1N~WF*d$7jk-mo#1wG&`^J+ z#$vDqhT|nohUM$ql(;*L&rvNlk0hw{N5+MEgg;Kr{Xm#7sv&vUEPy*hK(>fV9Hmjs zOR7Zn65wRFS;wqx%6^<>4UyE{A&C z;Kw(ux{N~&7~B+B%J<8}H18LAWH~gs#9vq6xB^J|Ap*Fd?nZEYU<8?DscE2<{(4 zAtp`8QhebjkmrgB5WL>cn#qE_tafAV!e2+BN3cvwhz|-_3P-Qlk4`OxaW6hj-`Uy{ zu#_9Q-|3g!PlQU(Zo^fk4RZOT$hH+gTKz=jKz`et!9Jqj;Q7;xC>t8S>dssOOg`|- z8lPFM^u6aN42(6{rU0yL@mz-t6=`)yw0^)E8@(mkGv)ZHPb)YS8|35?CQ;G~hIzkUJ` zi;5CGs2|LXhl`QG9Vj#71R%-!j2ggCXQk2g(1?}Zzb1hRNdk3sI|wQD0&LbBD!;qM zXK5+~)XQD!x|^iHc^5D4f3iFeE>V3-KmYBlw$8;BRh|0NVF$tNOk_aeKL?Dic3B3s z*A#)>pG?_#mjIwj{3f;t^1|x=5Ygn480~?~AE|_)Hb1ex0?Hrloa7mmjBF8T2vGeQ zG8K=ryhnbg)rXFO*1O&xNx(BmI6I#$T8wo;35Z|~imnF~xWO^*FBc{LsZgl-PI<8N zR4iz=m<2;d71Msi3tJZ@oiwnj$Tr@#{x(?I6=>VxmT`%+%jRFUm3(4$#qD0TMhn52 z&Tu$u=($h8{d178F&gWNG#Qlj_>Ay8gY9_6u;JS{EG;KtvSsxA^Z!Lu6naaGOI~ny zQa3E$S7I)B{y73>fdaXfS_AGNkbYT()u*%NaV!w0_Cl`WBiLL0}z> z1kl@Fo4dI^rtMq>*Z$EIu21pVTuTwva`p=bGf!DR?w4lb8MXx`F~Ih%Q09U=7{=3d z!JXh6`)7KH?5|qq6jhq<1W$-{d&ovJY^wMK6q_~spAWUNqAUR+K*~JMGv^+%gdT)` zkO}fF3N=zI7ZP=$p%j$}9wV@OikIO-l5{rfv6DXD`OkiocAJhCw@xa}Gt6+H)TC`K zJ}c@wz>!jwY>Uz7g5mQ5JWohdHvbq5nPf!oP{nPvi8H(eNU7T-3<+l% zl-{8^VFK+p0m%RUrl3*)vH3vuht)J2A#ixbHfK-lbf8Kf7<2%@td~xU5HqVU0C9DC z?2I7>6LhZk@LB~Y{FiwuTsRpDdNuC7|5Y`V{zo5mm%-wQ?87A-{-x8{`O#3@-Jj>3e!5-=t~~|4w-q;MIHyddh#%`9uDy_7JP% zO3hYk*C9){1kKg$E#|QFd&Po!wT4lgf}_Jqwp-8k zj(&0}>w%Or$C;_)1iws&5{iw|C?AYpzWM8V{4zb_g~*?OtOq{fxZJi(A$uh4b)=+G z*+Xqkvx!Hzler& zbjlj%(Z*7hw~|lYP5$IWn~i<%XL3XF-~O9uSkH%x*%#|r@Vxh2r z)UaCM!E7p(biCG*Y&obLq3yqxgL0k_tY13j|1})G%CbSdg3U9bbZ=EJ?SJ+H-q5M3 z^Ur__%Vi-xD)!3&B02~tYb+JUaQ3$ua>{CwrX1R}q^ks301xAl#6FM?b#B$aQA!O@ zz?oW7WKc=&a^1fr5;~C8rNX!>YXjBQJ}-|bO{PM;D>UN3ZDy6~j?o+3I$pB%egVQBt{P^w$^w&Dg~4*0 zs@vNwknO6;-xb&`KIIuGCDw%IWfgc(7}kc8pBH@ot}_yPm#^_9`yeRCt81ExRGq8! ze{BatLI2Sqk5YfhOm#t*DyJV@m3I~^T&zb7X6}^a=i=pq6gpKr$=rjJ?O|K zh9=1iwIbGYsQcMXP8!(jv*gBZs7%&94`Kpu{?%`8@7skxD)b1oPHpQLQG|Lis@%je zpY8$d9#Anu`S)z{BL7hfi_QO4E&Q!ISjatG=xIkyb}4jR<7&dQ68<_4Dx3siAc)JW z7ZscJ9?y_NGCoQoP7C}?B4~Z!-vuN>@z)Uc20$Z7c04r(ISl}dIl7Z3$m_CsGo{1U zNC6krMG07N@Qh6D&YKqqtNsx+`Fu+S*L#XT`f=+@GIS)rd>k9YI=|Ra*HM1n=WK&% zc#h2WMIomChb)zU0DHV^XZVxtBlnr}YCQYv%Ms6}kNLhCaDK$_y7CpCI$z-M1FcNn zmMJlTuD||*N6j6n*p-6bqgKoF=aR7di0);eP88j`#hdhwg7i5C zuogUgugVXIM`a(W4A;6H7tQ;igstfb6{n7Ygg)dN&4MLRHE_2?fW&zsqJhit-}(X| z`p!DIcCbs#(j@UG%dg2p{? zr}@$`daqak^`pBX71I~?>CHYiNl!3%WTBL< zu88C|xZ{x=?XH8r^%VW%jnd27M{0+h-jcH%UG?HPng%^E=W+$$S(`FFA^$ln@GyB< z{=m2Wp-*5EdtYouG@u4T{;B~t(W&f&A~#iiekaUel1!_WKVtq*duJXFW&8GV9%0njB1~b7 zC9-8^3T;Y=QlczP$i5V^J;<*aTe6KTMP_76MD`_n_MO2)mPjF6*_jwyyw_;a^Zef9 zc>jI>c>Z!2$35=*y081X&-46#&+Bt%bfbV+FYhTSGlm|LBXKBDU_LhQS~~K@d@0{( zGA?O%2zzsbuxsIC!aUj#>F@OFtD`w6X)lYhth$cT#v_KTCQ#jg+Ely+SqDKdg-&$* zS&JVyi zNDC7vLQ`XeKDi$;!v2IuDLPv+HgJv4Q#^2qi6{F}v0`-x60=SLLE_c>2K$3#eco1H z>!wC(bzww8j~t{MBw1i}384q((IH!ITP;pi!ip5vdB9==cPplhP+r+M>M_f+s(sL* zN95G)x<*!PYa@HXs}D%rU3EQq)6%B!b-weu{)px<%Two%Q%wo>Dl-y=6iPzXB-7CN z01_Z&qGtneIh(@3#@ObC&Dj)C+Q;K#AZFm*PkQq-Lzr6K1RCQKFn8Xt<5~KxZ15`r z5MPU-7wR^NGr#o+A+NV*sPR5dYsZB!I;vqC=OQ@3$koJFS8WgUA(as;{Zg=SEv|IEIGLB z$dZlf^OYO|I%-_AJ=ihR;HKyy4ab6FvS0`od#TxkT*4odK@%O8cej=QjM|HtZ30VX zd)%P8{_C3)zXbpQ1(Q2-ch-cVS!%strOwZOCCekAE*dk=rDs z19VBSro$`&Z|%7q)bfnJOvs?gUr<^3DZOm^L>5r&lvk)5|U{8b&I1)ub3pH>W9DXs>d9(g>L#Y`9 z$af*g3oiI3U)r-RAT@QW7n|A}MXPgI_G-|jIktx0o|e@s^LtU>ut7kPekrzq!&*NL zjZPmy!NB{$XW9KyU_b24=P1)<2t&${nUP++pb>ti*NFw2Gsy_6>{RBpj#=zk)*#uu z4Ym8-}_8qBuwX%;}2yGEcky z19ceaWG%`A?LPZCDvGE-=+3T+hk%Z&8?3Wwd|X3?gdt9|$XUURy4s@?jH_xN5p_c} zzD-#I5&crW;$=R9lyMtNS|eAv?gomD^J12OuQd|^v+o;0RzILiVy@BQCIc4D{l<=^U0T*4<;3N>tb|~vu|LuaBvP^GJX%Y- zvjpCfq=sCJ=STS}7qSFy*j2qhFxDQ!Mnz&(m3acBlkD)gzQaH4Y8wiT3Z}8`v9jI~ zp_Q;yjT$rSLx2u79YbW*tCNpHodb^Rj{m}7Ws+cIExxW976dRUuH{QAML0&$=bTJ_ zADJ0Y7LjpgGs_Zd@QB7#_aWYGdmv8&lKLN$@DFEoizOf;n>DHC42M*eAU;arI~w#D znwS%8B<0k%cy6jgzJ6%J#d}}R^=c-1 z-`Nuq!Btyek5em0RWX2TbIO(b%j#pMOIk09jxZGWSn zZ8!b0r20lLDRbN~-;`68f41e;A*@bD0FGKCHR5yg>}dDznKN6r&Iw6^-s}G9S<|HU z4}AX6O)yH6I7VKGxr||Lz1WYK(NwMK$qm5!-r@Gst=4Z%JN5d(J|T1&?{W9@iK|tG zxfw3e7M;Wvqz4V6()!+o_^!)YkX{pF-`9iYhO+4xyHACUOgy-@(BhLqTJxhNNRedTk@Udv-vMRw}d!{&fHEK34FyG>t zP2jypNTlN*OOs=hUApyw9nH-Knc`t=c&KL7A&NvZisR|X9azEgi7B;-Yis$0^ibt; zp${y&rIe5N85tO=-aZylm#$bfwSINdJYGqnza;bmo-`AU(P3yF&ilNmXxRp2vZKwC zErV8UF_i9J8F|wF7`TA8shF`?<4;^pXVWWElOsXL6qwvm5~dKD?6w5V1ukxl2(p-w13|fgh7P0s4tT(dy{*8qFAW zM7?Gtq5+kLF@X8yQBCaT0eQjR!7UgIOD0PMLwpIa;X7G+0muCnOGW8m!J`j(qRsiO zxXe@AzifU1a5wx8XNKT@9UM&M%y{LczQ^TU_es}54a=n0gqZ?fjjzSi{9+I@f0nVK zS3k48NoKo7vcC{G&(`9?c}}Qz34`%Fm&s+}n0|s4{W==+SjSVUEn&m0j39dB>=h|L zOP*tNJSltjAzl}Ym;%e$5#vQ$d~KaU1WMQS}{uiv&T0xCT|6 zV2a;>K7`T&5g?Vn00sb^W>3vyPY4;T+}0Ben&CFneTo<%A9IdJv=}2eySo?16g70nD^PC?NeL<48uT#+2C~2~ zea`WgkXkSCCr%kIEB#hVYRF1ha)lBkZ7;h{c@^f1MnGo&s zq_HI$fYKf4Hd{0?iSs2WB*+)dw&(=iX*e*!rLyRLINwZKPC9e~8U4Ey&1QK`y?e_* z;4H2468TAEKg1|SPXgO;8nl_)wM zRVRn-zh;&f_b4&{Dk;<9pG&t!ANCYB~QQJI@W0`jC z?}W}}kJz4um08J_F4CEaNWy`2-qRPtqbv+}Q|guQUsXgt$)wXba-p_&3iXZ~rn&aXU%$hf zb!AgvR4zJz?h(48^kbmA-9fF6V!<6!C)dDqEj8?WkA8`(9Q;gS44jv%F0O6B8dm&q zHSfERO};(e&RBh1n%tQ+WmpwF_&PiBmX#xB^G}SWC9~S8D#P}(6+7i0c?KM!{d$Fb zey@uW67LF|Y#=$Af&L+s*}&#uOap~L)-gh)hfo;$tHmIeU!;V zc4;U1OHiSjFMRR9zxH3@1fXiVc;iAqP9rig2+(`tP^|_-uBxesi*PDYbJehIwfG=y zUB+IrfD%(>fO~Lt)*Ua*eXkvcw|m~Zqrn3H5wM%Q%m@gJ3V;VCcVOdTl{d#shURrW zxFz0pt-t!4_dVa2mA)d&{CuzwImThEqQghwT@T(;4dsiw@A6LU8Eu@$`WLiSJ1G%; z$o6>}&Oawst7(Pkk=Ac#-ni%OMMHQa;jE(nP;V{NFjmuEu;;O7o0*4V_j2kaUXIy$ zpF;7vcl3kQ`&73ZFsZHqyIZ9)=lt~gr>_o$W63MuazLvh0*f~DSodqhnqeMI)6ncw zzo@LJ9g7}S$d?HIE?!RyJIrw`U5wPOIMw|KnrW(EF{CKukz~VADzK#gmR_H;p8Y~u zULS)|Xe!mkHIhC&H{ZXObDYxG7al59U!t`wnfsUB5j3nf%8%rDBD5p7j$-ig~D>1sEf4;fO zvr;`o$;YY5B;h8U6_1tVijZ>QgRH^psZkn9`-c#lI@SgHG0#tT7>pCXi2h}se}u7x zEX=0?dXyfeBrM3+mY-O;M73sZOUo0^$lC=j) zjdi|@)+ec=wJF!ElbGC7zy+WJ!OtRzbJo|(C4-8Gb;PtJIbGj%@vWua;}I{|QY5td z4+Cs+CKG^qf*RdJV4KZr3cQ!yF+i~qMTe3VZa(PTi%BPn%7+f4Ui*>Xcl1~vHAnbz z6&c*q#6xSuWzZpQgX2{daF65EaO8jYz*&2;qB&8Z<5WR@!^6byCCoJDqk1dJjhGmLXpxzVdk6|FW`eV*0IVLC=y;0NLgV3h;iAwR21?AzeLJ@ zrN>V`yjK3r0(Ts6#(4`V>jrRfhh)e_7L~B(%=Dg5hey`>8)d_zN8T!*+jHyRLN% zA^h{NYDq`ZLf-AmezVjP>-KSNV`zKp+q~y?1}1-#VRUq~a&!Es+sr%1;VN2z-9v;f zf~939MC?@ zY=5uTeKNLh6CQ2f;|BRq;#7#dNBQ7Zx%vtJ1->zB@2Q@zxO1sHU*l^7F5!KVef(FZ z=emW{D^+x?P$<;EwckRuM)x^bHEd;9m$N;~9b^f&Tc1ju`!!H%s&8E92ANa|c_;K_ z$pc09@XLi6Oe4d?39D9#5C5|^9_76|iXrzN1#7Q9nCEzDJF(oQeze-WHJWXOLa7{K zwihFtHNrhlhyAz#YQkOY*>iJu<(DGb-e{a&R3_MBIBLKU&2hx9)`4IQ&bjsOQ$7A~ z-(Eg0W$!I?xj#nYnLGVpooci9 zAgAf14+m(;cC=XP_s2{_)I=0&I6+{zt6Lman`?2vzMvX=hb${_PX}pC!P2| zzUvC);;)ms9Tar@N`@^E*ELra2lHJ?R0j#JQ^Ar25MMMN0WXy6?Y@?>kaS;%|#Ur<*f6@ GKK}#9b(c>7 literal 0 HcmV?d00001 diff --git a/site/assets/og-card.svg b/site/assets/og-card.svg new file mode 100644 index 0000000..132cc32 --- /dev/null +++ b/site/assets/og-card.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + Recall + Durable memory for AI coding agents + An open Agent OS pattern · brain + tiered memory · MCP-native + Works with Copilot, Claude, Cursor, Cline, Aider, Continue, LangChain + recall.works + github.com/stevepaltridge/recall.works + diff --git a/site/assets/site.css b/site/assets/site.css new file mode 100644 index 0000000..ac208d0 --- /dev/null +++ b/site/assets/site.css @@ -0,0 +1,176 @@ +/* @recall.works/site | site.css | v1.0 | 2026-05-07 | extracted from agent-os.html one-pager + nav additions */ + +:root { + --bg: #0d0f12; + --panel: #14181d; + --panel-2: #1a1f26; + --border: rgba(255,255,255,0.08); + --text: #d8dde3; + --text-dim: #8a93a0; + --text-faint: #565d68; + --accent: #C7802F; + --accent-soft: rgba(199,128,47,0.12); + --good: #6fae5a; + --warn: #d9a441; +} +* { box-sizing: border-box; } +html, body { + margin: 0; padding: 0; + background: var(--bg); color: var(--text); + font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; +} +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; } +code, pre, .mono { font-family: "JetBrains Mono", Consolas, "Courier New", monospace; } + +/* --- Top nav --- */ +.topnav { + position: sticky; top: 0; z-index: 10; + background: rgba(13,15,18,0.92); + backdrop-filter: blur(8px); + border-bottom: 1px solid var(--border); +} +.topnav-inner { + max-width: 1080px; margin: 0 auto; + padding: 14px 32px; + display: flex; align-items: center; gap: 28px; + flex-wrap: wrap; +} +.topnav .logo { + font-family: Georgia, "Times New Roman", serif; + font-size: 22px; font-weight: 700; + color: var(--accent); letter-spacing: -0.02em; + text-decoration: none; +} +.topnav .logo sup { font-size: 11px; color: var(--text-faint); margin-left: 2px; font-family: -apple-system, sans-serif; font-weight: 400; } +.topnav nav { display: flex; gap: 22px; flex-wrap: wrap; margin-left: auto; } +.topnav nav a { + color: var(--text-dim); font-size: 13px; + letter-spacing: 0.04em; +} +.topnav nav a.active, .topnav nav a:hover { color: var(--accent); text-decoration: none; } + +/* --- Wrap --- */ +.wrap { max-width: 1080px; margin: 0 auto; padding: 56px 32px 96px; } +.wrap.narrow { max-width: 800px; } + +/* --- Header / hero --- */ +header.page-header { border-bottom: 1px solid var(--border); padding-bottom: 36px; margin-bottom: 56px; } +.brand { font-size: 56px; font-weight: 700; letter-spacing: -0.035em; color: var(--accent); line-height: 1; margin-bottom: 8px; font-family: Georgia, "Times New Roman", serif; } +.brand .tm { font-size: 16px; font-weight: 500; vertical-align: super; margin-left: 4px; color: var(--text-faint); letter-spacing: 0; font-family: -apple-system, sans-serif; } +.eyebrow { font-size: 11px; letter-spacing: 0.18em; color: var(--text-dim); text-transform: uppercase; margin-bottom: 22px; font-weight: 600; } +h1 { font-size: 38px; font-weight: 600; line-height: 1.15; margin: 0 0 18px; letter-spacing: -0.02em; color: var(--text); } +h1 .accent { color: var(--accent); } +.lede { font-size: 18px; color: var(--text-dim); max-width: 720px; margin: 0; } + +/* --- Sections --- */ +section { margin-bottom: 64px; } +h2 { font-size: 13px; letter-spacing: 0.16em; color: var(--text-faint); text-transform: uppercase; font-weight: 600; margin: 0 0 22px; padding-bottom: 10px; border-bottom: 1px solid var(--border); } +h3 { font-size: 17px; font-weight: 600; margin: 0 0 6px; color: var(--text); } +p { margin: 0 0 14px; color: var(--text-dim); } +p strong { color: var(--text); font-weight: 600; } + +/* --- Pillars grid --- */ +.pillars { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; } +.pillar { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 22px 24px; } +.pillar .tag { display: inline-block; font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); background: var(--accent-soft); padding: 3px 8px; border-radius: 3px; margin-bottom: 12px; font-weight: 600; } +.pillar p { margin: 0; font-size: 14px; } +.pillar a { color: var(--text-dim); } +.pillar a:hover { color: var(--accent); } + +/* --- Architecture diagram --- */ +.arch { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 28px; } +.arch-row { display: grid; grid-template-columns: 140px 1fr; gap: 20px; align-items: start; padding: 14px 0; border-bottom: 1px dashed var(--border); } +.arch-row:last-child { border-bottom: none; } +.arch-label { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); font-weight: 600; padding-top: 4px; } +.arch-cells { display: flex; gap: 10px; flex-wrap: wrap; } +.cell { flex: 1; min-width: 180px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 6px; padding: 12px 14px; } +.cell .name { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 4px; } +.cell .what { font-size: 12px; color: var(--text-dim); line-height: 1.45; } +.cell .where { display: block; font-size: 11px; color: var(--text-faint); margin-top: 6px; font-family: "JetBrains Mono", Consolas, monospace; } + +/* --- Stat tiles --- */ +.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; } +.stat { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 18px 20px; } +.stat .num { font-size: 26px; font-weight: 600; color: var(--accent); letter-spacing: -0.02em; } +.stat .lbl { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); margin-top: 4px; font-weight: 600; } + +/* --- Flow --- */ +.flow { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 24px 28px; } +.flow ol { margin: 0; padding-left: 22px; } +.flow li { margin-bottom: 12px; color: var(--text-dim); padding-left: 8px; } +.flow li strong { color: var(--text); display: block; margin-bottom: 2px; } + +/* --- Code block --- */ +pre.code { background: #0a0c0f; border: 1px solid var(--border); border-radius: 6px; padding: 16px 18px; font-size: 13px; color: #b8c2cc; overflow-x: auto; margin: 14px 0; } +pre.code .c { color: var(--text-faint); } +pre.code .k { color: var(--accent); } + +/* --- Comparison --- */ +.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; } +.compare .col { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 22px 24px; } +.compare .col.before { opacity: 0.65; } +.compare h4 { margin: 0 0 14px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-faint); } +.compare .col.after h4 { color: var(--accent); } +.compare ul { margin: 0; padding-left: 18px; color: var(--text-dim); font-size: 14px; } +.compare li { margin-bottom: 8px; } + +/* --- Hardware reality table --- */ +.hw { width: 100%; border-collapse: collapse; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; } +.hw th, .hw td { text-align: left; padding: 12px 16px; font-size: 13px; border-bottom: 1px solid var(--border); } +.hw th { background: var(--panel-2); color: var(--text-faint); font-weight: 600; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; } +.hw tr:last-child td { border-bottom: none; } +.hw td.profile { color: var(--text); font-weight: 600; } +.hw td.verdict.good { color: var(--good); } +.hw td.verdict.warn { color: var(--warn); } +.hw td.verdict.bad { color: #c8554a; } + +/* --- Baselines list --- */ +.base { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 8px 0; } +.base-row { display: grid; grid-template-columns: 200px 1fr; gap: 24px; padding: 14px 24px; border-bottom: 1px solid var(--border); align-items: baseline; } +.base-row:last-child { border-bottom: none; } +.base-name { font-size: 14px; font-weight: 600; color: var(--text); } +.base-name .scope { display: block; font-size: 11px; color: var(--text-faint); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; margin-top: 2px; } +.base-note { font-size: 13px; color: var(--text-dim); } +.base-note em { color: var(--accent); font-style: normal; } + +/* --- CTA buttons --- */ +.cta-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 22px; } +.cta { display: inline-block; padding: 11px 20px; border-radius: 6px; font-size: 14px; font-weight: 600; letter-spacing: 0.02em; } +.cta.primary { background: var(--accent); color: #0d0f12; } +.cta.primary:hover { background: #d8923f; text-decoration: none; } +.cta.ghost { background: transparent; color: var(--accent); border: 1px solid var(--accent); } +.cta.ghost:hover { background: var(--accent-soft); text-decoration: none; } + +/* --- Hero (landing) --- */ +.hero { padding: 72px 0 48px; border-bottom: 1px solid var(--border); margin-bottom: 56px; } +.hero .brand-xl { font-family: Georgia, "Times New Roman", serif; font-weight: 700; font-size: 112px; line-height: 1; letter-spacing: -3px; color: var(--accent); margin: 0 0 12px; } +.hero .brand-xl sup { font-size: 22px; vertical-align: super; margin-left: 6px; color: var(--text-faint); font-family: -apple-system, sans-serif; font-weight: 400; } +.hero .tagline { font-size: 26px; line-height: 1.4; color: var(--text); max-width: 760px; margin: 0 0 14px; font-weight: 500; } +.hero .sub { font-size: 16px; color: var(--text-dim); max-width: 720px; margin: 0; } + +/* --- Index card grid (landing) --- */ +.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 8px; } +.card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 22px 24px; transition: border-color 0.15s; } +.card:hover { border-color: var(--accent); text-decoration: none; } +.card h3 { color: var(--accent); margin-bottom: 8px; font-size: 16px; } +.card p { font-size: 13px; margin: 0; } + +/* --- Footer --- */ +footer.site-footer { margin-top: 80px; padding-top: 28px; border-top: 1px solid var(--border); color: var(--text-faint); font-size: 12px; } +footer.site-footer .meta { display: flex; gap: 24px; flex-wrap: wrap; } +footer.site-footer .meta div strong { color: var(--text-dim); } + +/* --- Responsive --- */ +@media (max-width: 720px) { + .wrap { padding: 32px 20px 64px; } + .topnav-inner { padding: 10px 18px; gap: 14px; } + .topnav nav { gap: 14px; margin-left: 0; } + .brand { font-size: 40px; } + .hero .brand-xl { font-size: 64px; } + .hero .tagline { font-size: 20px; } + h1 { font-size: 28px; } + .pillars, .compare, .stats, .cards { grid-template-columns: 1fr; } + .arch-row { grid-template-columns: 1fr; } + .base-row { grid-template-columns: 1fr; gap: 4px; } +} diff --git a/site/brain.html b/site/brain.html new file mode 100644 index 0000000..1e01c80 --- /dev/null +++ b/site/brain.html @@ -0,0 +1,208 @@ + + + + + + +The brain · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +

+ +
+ +
+ + + +
+

What it actually is

+

A vector database fronted by an MCP server. Plain Python, plain HTTP, plain Server-Sent Events. The reference implementation runs Chroma inside a small container; the MCP layer exposes a handful of tools the agent can call.

+
+
+ Storage +

Chroma vector DB

+

One persistent client. A frozen read collection (curated corpus, baked into the image) plus a sidecar write collection (lazy-created at first remember()). Same DB file, no schema migration to add memories.

+
+
+ Surface +

MCP server over HTTP/SSE

+

One container, one URL, one auth header. Any MCP-aware agent can connect: VS Code, Claude Desktop, Cursor, custom harnesses. No per-seat database file. No drift between teammates.

+
+
+ Hosting +

Local Docker or cloud container app

+

Same image works on a laptop with docker compose up or in Azure Container Apps / Cloud Run / Fly / wherever. Persistent volume for the Chroma file is the only stateful piece.

+
+
+
+ +
+

The tool surface

+

The agent doesn't query SQL. It calls these like any other tool:

+
# fuzzy semantic recall across the whole corpus + every memory ever written
+recall(query="how does the auth refresh flow handle expired tokens", n=8)
+
+# write a durable memory; goes into the sidecar collection, queryable forever
+remember(text="index migration must run before the schema validator...",
+         source="S-20260507-deploy-pipeline",
+         tags=["deploy", "migrations"])
+
+# lightweight liveness + recent-activity ping at session start
+pulse()
+
+# save working state mid-session so the next agent can pick up
+checkpoint(summary="...short status...")
+
+# write a structured reflection after a thorny investigation
+reflect(topic="why the cache layer kept returning stale rows", lessons=[...])
+

Exact tool names and signatures live in the reference repo. The shape stays the same across implementations: read fuzzily, write durably, ping cheaply.

+
+ +
+

What goes in it

+
+
+
Curated corpus
+
+
+
Domain documentation
+
SDK references, API specs, agency rule sets, forum scrapes — whatever the agent needs to answer questions in your domain without re-googling.
+ frozen read collection +
+
+
Codebase chunks
+
Optional. Code split into semantic chunks at build time so the agent can fuzzy-find prior implementations.
+ frozen read collection +
+
+
External corpora
+
Anything you ingest once and never touch again — RFCs, standards, vendor whitepapers, previous-employer documentation you're allowed to keep.
+ frozen read collection +
+
+
+
+
Live memory
+
+
+
Audit-trail rows
+
Every closed session writes one row. Tagged with session id + topic. Becomes searchable history of every decision ever made.
+ sidecar write collection +
+
+
Session journals
+
Each REVIVAL doc gets ingested at close. The agent who picks up tomorrow can recall("last time we touched X") and get the dossier.
+ sidecar write collection +
+
+
Ad-hoc remember() calls
+
Whenever the agent finds something worth keeping mid-session — a gotcha, an anti-pattern, a pricing footgun — it lands here immediately.
+ sidecar write collection +
+
+
+
+
+ +
+

How it's different from /memories/

+

Both are persistent. Both survive between sessions. They serve different jobs:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 /memories/ filesThe brain
AccessExact text. The agent grep's, reads, edits.Fuzzy semantic. The agent asks a question, gets the closest N chunks back.
SizeHundreds of KB. Hand-curated. Auto-loaded into context (the top tier).Tens of thousands of chunks. Never loaded whole. Queried just-in-time.
Edit shapeThe agent rewrites files in place. Diffs visible in git.Append-only by convention. Old memories aren't deleted, just outvoted by newer relevant ones.
Job"What do I always need to know?" — routing rules, preferences, top-of-mind facts."Has anyone seen this before?" — cross-session, cross-project, cross-domain recall.
Failure modeFiles get long. Agent gets distracted. Triage with the local-model compressor.Stale memories slowly drift. Worst case = a recall pulls something that's a year out of date. The audit-trail in /memories/ stays canonical.
+

Rule of thumb: if you'd want to load it every turn, it's a memory. If you want to recall it later, that's a brain entry. Memory is triage. Brain is the library.

+
+ +
+

Networked pattern

+

The brain is the only Agent OS pillar that's a service rather than a file pattern. That's deliberate. Once it's a service, every agent on every machine can hit the same recall surface — no per-seat duplication, no re-embedding, no drift between teammates.

+

The architecture detail of how a multi-agent setup shares one brain — frozen+sidecar merge at query time, coordination primitives, audit-trail-as-ground-truth — lives on the architecture page. This page is about what's in the brain. That page is about how it scales.

+
+ +
+

Cost & backup

+

A small container app instance + a few hundred MB of vector data costs roughly $0.30/month in cloud compute on the documented setup. The vault pillar handles backup: weekly snapshot of the Chroma file to vault/brain/, two newest kept hot, plus a sealed local .SEALED.zip with sentinel files preventing the agent from mistaking it for live data.

+

Restoration is three steps: rename, expand, point the container at the restored volume. See architecture for the cold-storage tier diagram and hardware reality for the cost breakdown.

+
+ +
+

Why this matters

+

Without the brain, the agent's long-term memory is whatever fits in the auto-loaded files. That works for routing rules and preferences. It does not work for "we hit this exact bug eight months ago, here's what we tried, here's what finally worked."

+

With the brain, the agent walks into every session with access to every prior session's findings, every piece of vendor documentation you ever ingested, every anti-pattern you ever flagged. Cold-start stops being cold. Repeated mistakes stop repeating. The compounding effect is the entire reason this layer exists.

+
+ + + +
+ + diff --git a/site/comparison.html b/site/comparison.html new file mode 100644 index 0000000..a9a4bdd --- /dev/null +++ b/site/comparison.html @@ -0,0 +1,137 @@ + + + + + + +Compare · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

What it replaces

+
+
+

Default agent experience

+
    +
  • Cold start every chat. "Read the scrollback."
  • +
  • Auto-compaction picks what survives. Lossy by surprise.
  • +
  • Chat-only memory. Disk reality drifts from agent reality.
  • +
  • No cost ceiling. Bug in a loop = morning email from billing.
  • +
  • Backups are someone else's job.
  • +
  • Audit = scrollback search.
  • +
+
+
+

Agent OS

+
    +
  • Cold start reads a 3KB curated brief. Zero context loss.
  • +
  • Compaction can happen safely — durable memory survives it.
  • +
  • Memory tiers map to disk, vector brain, and immutable cloud.
  • +
  • Three-layer cost gate. Worst case = abort, never overspend.
  • +
  • Nightly azcopy + weekly brain snapshot + sealed local copy.
  • +
  • Audit-trail with one row per session. Always greppable.
  • +
+
+
+
+ +
+

How this fits next to existing tools

+

Plenty of good work exists in this space. Calling out the baselines so the contribution here is precise — Agent OS is the combination, not any one piece.

+
+
+
GitHub Copilot Chat memory
tiered memory · per workspace
+
The actual host platform behind the reference implementation. Provides the memory tiers Agent OS leans on. What's missing in the box: durable cold storage, cost gates, the discipline conventions, the local-model distillation.
+
+
+
Cursor · .cursorrules
project-scoped instructions
+
Solves preference persistence and routing. No durable journal, no audit trail, no cold-start protocol, no cost gates. Sits at the same tier as the routing rules in /memories/.
+
+
+
Cline / Roo Code
custom-instructions + agentic loops
+
Strong on agentic tool use. Memory is per-conversation. Same gap as default Copilot: no durable layer between conversations, no cost gate, no immutable audit.
+
+
+
Aider · .aider.chat.history
conversation log + git commits
+
Audit-as-git is excellent — every change is a commit. Closest existing analog to the audit-trail pillar. Doesn't have the brain, the vault, or the cost gates.
+
+
+
Continue.dev
configurable IDE assistant
+
Configurable model routing and context providers. Comparable to the routing layer. Memory and audit story is lighter; no cold-storage tier.
+
+
+
LangChain / LlamaIndex memory
programmatic memory abstractions
+
Library-level building blocks for memory. You'd assemble something like the memory + brain pillars on top of these. Doesn't speak to discipline conventions or cost gates — that's outside their scope.
+
+
+
AutoGen · CrewAI · smol-agents
multi-agent orchestration
+
Solves how agents coordinate during a session. Agent OS is concerned with what survives between sessions. Complementary, not competing — wire either of these on top of the brain layer for multi-agent.
+
+
+

What's distinctive here: the tiered-memory + WORM-vault + fail-closed cost gate + local-model distiller + networked brain — assembled and disciplined as one architecture, with conventions that keep the agent honest. Each individual pillar has prior art. The integration is the point.

+
+ +
+

A note on which AI you're driving

+

The reference implementation was field-tested with Claude (Sonnet / Opus class) running inside GitHub Copilot Chat in VS Code. That combination shaped some of the conventions:

+
    +
  • The /memories/ tier scopes (user / session / repo) match Copilot Chat's memory-tool surface. Other hosts expose memory differently — the pattern still applies, the file paths and load triggers may not.
  • +
  • MCP tool calling, the specific way read_file / grep_search / run_in_terminal compose, and the brain's HTTP/SSE bridge were tuned against Claude's tool-use behavior. Other models route through tools with different latency, different parallelism, and different willingness to read large context.
  • +
  • The cold-start protocol assumes the agent will actually read a 3KB brief instead of paraphrasing it. That's been more reliable with Claude than with smaller or earlier-generation models in the same harness.
  • +
  • Branding stamps, audit-trail discipline, and the fix-at-root reflex are conventions encoded in instruction files. They depend on the host honoring instruction files at all — which varies a lot across editors, models, and product versions.
  • +
+

Run the same architecture against a different agent and expect to retune. The pattern is portable; the specific cadence isn't. Treat anything in the reference scripts as a starting point, not a contract.

+
+ + + +
+ + diff --git a/site/hardware.html b/site/hardware.html new file mode 100644 index 0000000..6003dd4 --- /dev/null +++ b/site/hardware.html @@ -0,0 +1,120 @@ + + + + + + +Hardware reality · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

By the numbers

+
+
<$1
Azure Blob storage
+
7 yr
WORM retention
+
~3 KB
Cold-start brief
+
3
Independent fail-safes
+
+
+ +
+

Profile-by-profile breakdown

+

Everything in Agent OS besides local-model distillation (memory tiers, vault, guardrails, audit-trail, continuity discipline) works on any machine that runs your editor. The table below is specifically about the distillation pillar.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProfileLocal modelDistill speedVerdict
Workstation, 16 GB+ VRAM
RTX 4080/5080/5090, M3/M4 Max, similar
14B coder model, full quality~3–15 sec / summaryReference-implementation experience.
Mid-range laptop, 8 GB VRAM
RTX 3060/4060, M2 Pro, etc.
7B coder model, q4 quantized~10–30 sec / summaryWorkable. Summaries shorter, slightly noisier.
Integrated graphics
no discrete GPU
3B model on CPU, or hosted small model~30–90 sec / summarySlow but functional. Or skip local entirely and use a cheap hosted model — the spend gate keeps it bounded.
Phone-class computeNot the target. The pattern needs some available compute for distillation.
+

The five non-compute pillars don't care about the GPU. If you can run an editor and reach object storage, you can run Memory + Vault + Guardrails + Brain backup + Continuity unchanged. Local compute is the cherry on top, not the load-bearing wall.

+
+ +
+

Cost expectation

+

Reference implementation, on the documented setup, has run for months at well under $1/month in cloud spend. The line items:

+
    +
  • Object storage (Cool tier): $0.01/GB/month for the active draft container. ~200 GB ≈ $2/mo nominal, but Archive lifecycle drops most of it to $0.00099/GB/month within 30 days.
  • +
  • Vector brain (cloud-hosted): a small container app instance, ~$0.30/mo for hobbyist usage. Network egress dwarfs compute; tens of millions of recall queries fit comfortably in the free tier of most provider networks.
  • +
  • Local compute: $0.00. The local model never bills.
  • +
  • Egress / API calls: negligible. The agent's expensive token stream is paid by the host editor, not Agent OS.
  • +
+

The reference spend-gate script ships with a $25/month ceiling as the default circuit breaker. It's not a target spend or a recommendation — it's a number that makes a runaway script hit a wall instead of a billing email. Replace it with whatever number you want; the gate just needs to fail-closed before it touches money.

+
+ + + +
+ + diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..af83f40 --- /dev/null +++ b/site/index.html @@ -0,0 +1,136 @@ + + + + + + +Recall™ — durable memory for AI coding agents + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
Recall
+

Durable memory, audit, and continuity for AI coding agents.

+

An open reference architecture. Free to read, free to use, free to adapt. Six pillars, a small set of conventions, and ~600 lines of glue that turn any AI coding agent into a contractor with a project log instead of a goldfish.

+ +
+ +
+

Start here

+ +
+ +
+

What it solves

+

Modern AI coding agents are stateless. Every conversation starts cold. Memory is what the host platform decides to keep. Costs are unbounded. Audit is whatever the chat transcript happens to retain. Multi-day campaigns degrade into "we already discussed this — read the scrollback" loops, until eventually the scrollback gets compacted by an opaque summarizer and detail vanishes.

+

Agent OS treats the agent like a contractor who clocks in every day: they don't remember yesterday's work from their own head, they read the project log. The log lives on disk, in a vector brain, and in immutable cloud storage. The agent's job is to keep that log honest and to read it before acting.

+
+ +
+

By the numbers

+
+
<$1
Azure Blob storage
+
7 yr
WORM retention
+
~3 KB
Cold-start brief
+
3
Independent fail-safes
+
+
+ +
+
+
Reference implementation: VS Code + GitHub Copilot Chat + an object-storage backend + a local open-weights model on a consumer GPU. Not bound to any of these — swap freely.
+
License posture: open pattern. The whitepaper is shared freely; the reference implementation is permissively licensed (MIT). Attribution to Recall™ appreciated.
+
Recall™ trademark application pending. Use the ™ designation in any republication; switch to ® once the registration is granted.
+
Site generated: 2026-05-07.
+
+
+ +
+ + diff --git a/site/pillars.html b/site/pillars.html new file mode 100644 index 0000000..6deed2c --- /dev/null +++ b/site/pillars.html @@ -0,0 +1,109 @@ + + + + + + +Six pillars · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

Pillar grid

+
+
+ Memory +

Tiered, durable, agent-readable

+

User memory auto-loads every turn (~200 lines, ~30KB). Reference memory loads on demand. Session memory is scratch. Repo memory holds verified facts. A semantic vector brain handles fuzzy recall across tens of thousands of chunks.

+
+
+ Local compute +

Zero-cost compression and distillation

+

A local open-weights model on a consumer GPU compresses verbose memory, distills brain recalls, generates cold-start briefs, and writes rolling summaries that pre-empt host-side compaction — all without spending a token of paid context. The expensive model thinks; the free model summarizes.

+
+
+ Vault +

WORM-immutable backup, 7-year retention

+

Nightly object-storage sync of every workspace byte. Time-based immutability blocks any delete, overwrite, even with the master key. Cool tier auto-tiers to Archive after 30 days. ~200 GB stored at well under a dollar a month.

+
+
+ Guardrails +

Three layers, fail-closed

+

Kill-switch sentinel + spend-gate script + cloud budget alert. Every billable script must clear all three before touching money. Default ceiling configurable. Failure mode = abort, never silently overspend.

+
+
+ Brain backup +

Two cloud copies + one sealed local

+

Weekly snapshot to vault/brain/. Two newest kept hot. Plus a sealed .SEALED.zip on local disk with sentinel files preventing the agent from mistaking it for live data. Restoration: rename + expand, three steps.

+
+
+ Continuity +

Cold-start in 60 seconds

+

Per-session journals + a one-line audit trail + the local-model distiller produce a ~3KB curated brief on demand. The successor agent reads it instead of guessing from a lossy auto-summary. Context survives compaction, restart, model swap.

+
+
+
+ +
+

How they compose

+

Each pillar can run alone — but the leverage comes from the combination:

+
    +
  • Memory + Continuity means the next session knows what this one decided.
  • +
  • Local compute + Memory means memory stays compressed and queryable without burning paid context.
  • +
  • Vault + Brain backup means every byte the agent ever touched is restorable for seven years.
  • +
  • Guardrails + everything means none of the above can run away with your wallet.
  • +
+

For the architecture diagrams of how the pieces wire together, see the architecture page. For an honest take on what each profile of hardware actually needs, see hardware reality.

+
+ + + +
+ + diff --git a/site/quickstart.html b/site/quickstart.html new file mode 100644 index 0000000..dccab73 --- /dev/null +++ b/site/quickstart.html @@ -0,0 +1,217 @@ + + + + + + +Quickstart · Recall™ Agent OS + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

The cold-start protocol

+
# 1. Load routing rules + preferences (auto-loaded; this is the manual form)
+Get-Content /memories/00-routing.md
+
+# 2. Generate a curated cold-start brief — local model, ~60 sec, zero-cost
+pwsh tools/qwen-coldstart.ps1
+
+# 3. Read the latest session journal (compressed if >24h old)
+pwsh tools/latest-revival.ps1 -N 1
+

Paths shown are from the reference implementation. Equivalent flows compose easily on macOS / Linux / any shell.

+
+ +
+

Install the reference implementation

+

The reference repo ships a self-contained scaffold: 9 PowerShell scripts, a brain container blueprint, 4 starter memory templates, an installer, and a config file you copy from config.example.json and fill in.

+
# Windows (PowerShell 7+)
+git clone https://github.com/RecallWorks/Recall
+cd agent-os
+Copy-Item config.example.json config.json
+# edit config.json — workspaceId, storage account, ceiling
+pwsh ./bootstrap.ps1
+
+# macOS / Linux
+git clone https://github.com/RecallWorks/Recall
+cd agent-os
+cp config.example.json config.json
+# edit config.json
+./install.sh
+

Bootstrap registers four scheduled tasks (vault sync nightly, vault promote weekly, brain snapshot weekly, rolling summary every 15 min), copies starter memory templates into your editor's memory dir, and runs the spend-gate self-test.

+
+ +
+

What ships in the repo

+
+
+
bin/
+
+
+
spend-gate.ps1
+
Three-layer fail-closed cost gate. Kill switch, cooldown cache, MTD spend check.
+ Layer 1 of 3 +
+
+
vault-sync.ps1
+
Nightly azcopy of workspace + memory + touched-folder log to draft container.
+ Cool tier · 24h SAS +
+
+
vault-promote.ps1
+
Weekly promote of stable draft contents into WORM-immutable vault.
+ Archive tier · 7yr +
+
+
brain-snapshot.ps1
+
Weekly snapshot of vector brain to vault. Two newest kept hot. Sealed local copy.
+ vault/brain/ +
+
+
+
+
bin/ (cont.)
+
+
+
qwen-coldstart.ps1
+
Curated ~3KB cold-start brief. State files + audit-trail tail + newest journal → local model.
+ ~60 sec, zero cost +
+
+
qwen-rolling-summary.ps1
+
Every 15 min, summarize the active transcript before host compaction lands.
+ /memories/session/*-rolling.md +
+
+
latest-revival.ps1
+
Find the newest session journal. Auto-compress with local model if >24h old.
+ REVIVAL-*.md +
+
+
mark-touched.ps1
+
Register an out-of-workspace folder so the next vault-sync grabs it.
+ state/agent-touched-folders.log +
+
+
+
+
templates/
+
+
+
00-routing.md.tmpl
+
Routing triggers, cold-start protocol, memory layout. Copy into your /memories/ root.
+ starter routing rules +
+
+
audit-trail.md.tmpl
+
Format spec for the one-row-per-session decision log.
+ | S-id | STATUS | summary | +
+
+
REVIVAL-template.md
+
Standard layout for per-session detail journals.
+ structured dossier +
+
+
fix-at-root-reflex.md.tmpl
+
Encoded discipline rule: notice bug in shared infra → fix source first, never route around.
+ discipline convention +
+
+
+
+
brain/
+
+
+
Dockerfile
+
Pinned ChromaDB + FastAPI + sentence-transformers image. Builds restart-safe brain service.
+ recall.works/brain:v0.2 +
+
+
docker-compose.yml
+
Single-service compose. Named volume, port 8080, health probe.
+ one-command spin-up +
+
+
recall.py
+
v0.1 stub with /health endpoint. Full server is on the v0.2 roadmap.
+ FastAPI + SSE +
+
+
agency_sidecar_patch.md
+
Design note: frozen-read + writable-sidecar pattern, merge-by-distance at query time.
+ architecture explainer +
+
+
+
+
+ +
+

Where this could matter

+

Long-running coding campaigns. When work spans weeks across many sessions and any detail loss costs hours of rediscovery.

+

Regulated environments. WORM-immutable audit trail with cryptographic time-based retention. Every session, every decision, every command — restorable for 7 years.

+

Multi-agent handoffs. When one agent finishes and a different model picks up. Curated brief + audit-trail + repo memory mean the receiving agent doesn't start cold.

+

Cost-sensitive autonomy. When the agent has authority over billable resources. Three-layer fail-closed cost gate plus outside-in budget alert means autonomy without surprise bills.

+
+ +
+

Where to go next

+ +
+ +
+
+
Recall™ trademark application pending. Use the ™ designation in any republication.
+
License: reference implementation is MIT. Whitepaper is shared freely. Attribution to Recall™ appreciated.
+
Site generated: 2026-05-07.
+
+
+ +
+ + diff --git a/site/robots.txt b/site/robots.txt new file mode 100644 index 0000000..d6b1cbc --- /dev/null +++ b/site/robots.txt @@ -0,0 +1,5 @@ +# @wbx-modified copilot-a3f7·MTN | 2026-05-08 | initial robots.txt +User-agent: * +Allow: / + +Sitemap: https://recall.works/sitemap.xml diff --git a/site/sitemap.xml b/site/sitemap.xml new file mode 100644 index 0000000..e83870e --- /dev/null +++ b/site/sitemap.xml @@ -0,0 +1,12 @@ + + + + https://recall.works/monthly1.0 + https://recall.works/whitepaper.htmlmonthly0.9 + https://recall.works/pillars.htmlmonthly0.8 + https://recall.works/architecture.htmlmonthly0.8 + https://recall.works/brain.htmlmonthly0.8 + https://recall.works/hardware.htmlmonthly0.7 + https://recall.works/comparison.htmlmonthly0.8 + https://recall.works/quickstart.htmlmonthly0.9 + diff --git a/site/whitepaper.html b/site/whitepaper.html new file mode 100644 index 0000000..efa17cf --- /dev/null +++ b/site/whitepaper.html @@ -0,0 +1,419 @@ + + + + + + +Recall · Agent OS — whitepaper + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+

What this is

+

A reference architecture, not a product. Six composable pillars, a small set of conventions, and ~600 lines of glue that turn any AI coding agent into a contractor with a project log instead of a goldfish.

+

The diagrams below describe the pattern. The code in the reference implementation is permissively licensed and was built around VS Code, GitHub Copilot Chat, an object-storage backend, and a local open-weights model on a consumer GPU — but nothing here is bound to those choices. Swap the host editor, swap the cloud, swap the local model. The pattern stands.

+
+ +
+

The problem this solves

+

Modern AI coding agents are stateless. Every conversation starts cold. Memory is what the host platform decides to keep. Costs are unbounded. Audit is whatever the chat transcript happens to retain. Multi-day campaigns degrade into "we already discussed this — read the scrollback" loops, until eventually the scrollback gets compacted by an opaque summarizer and detail vanishes.

+

Agent OS treats the agent like a contractor who clocks in every day: they don't remember yesterday's work from their own head, they read the project log. The log lives on disk, in a vector brain, and in immutable cloud storage. The agent's job is to keep that log honest and to read it before acting.

+
+ +
+

Six pillars

+
+
+ Memory +

Tiered, durable, agent-readable

+

User memory auto-loads every turn (~200 lines, ~30KB). Reference memory loads on demand. Session memory is scratch. Repo memory holds verified facts. A semantic vector brain handles fuzzy recall across tens of thousands of chunks.

+
+
+ Local compute +

Zero-cost compression and distillation

+

A local open-weights model on a consumer GPU compresses verbose memory, distills brain recalls, generates cold-start briefs, and writes rolling summaries that pre-empt host-side compaction — all without spending a token of paid context. The expensive model thinks; the free model summarizes.

+
+
+ Vault +

WORM-immutable backup, 7-year retention

+

Nightly object-storage sync of every workspace byte. Time-based immutability blocks any delete, overwrite, even with the master key. Cool tier auto-tiers to Archive after 30 days. ~200 GB stored at well under a dollar a month.

+
+
+ Guardrails +

Three layers, fail-closed

+

Kill-switch sentinel + spend-gate script + cloud budget alert. Every billable script must clear all three before touching money. Default ceiling configurable. Failure mode = abort, never silently overspend.

+
+
+ Brain backup +

Two cloud copies + one sealed local

+

Weekly snapshot to vault/brain/. Two newest kept hot. Plus a sealed .SEALED.zip on local disk with sentinel files preventing the agent from mistaking it for live data. Restoration: rename + expand, three steps.

+
+
+ Continuity +

Cold-start in 60 seconds

+

Per-session journals + a one-line audit trail + the local-model distiller produce a ~3KB curated brief on demand. The successor agent reads it instead of guessing from a lossy auto-summary. Context survives compaction, restart, model swap.

+
+
+
+ +
+

Architecture at a glance

+
+ +
+
Hot context
+
+
+
User memory
+
Auto-loaded every turn. Routing rules, preferences, audit-trail tail.
+ /memories/*.md +
+
+
Session memory
+
Per-conversation scratch. Cleared on close.
+ /memories/session/ +
+
+
Repo memory
+
Codebase facts. Append-only, verified at write time.
+ /memories/repo/ +
+
+
+ +
+
Warm context
+
+
+
Reference memory
+
Loaded on routing trigger. Topic-scoped per project area. Listed but not auto-included.
+ /memories/reference/ +
+
+
Semantic brain
+
Tens of thousands of chunks. Fuzzy recall across SDKs, documentation, prior work, and decisions.
+ vector store · cloud-hosted +
+
+
Cold-start brief
+
Local-model-distilled ~3KB summary of state files + last N audit rows + newest session journal.
+ coldstart distiller +
+
+
+ +
+
Cold storage
+
+
+
Draft container
+
Mutable working backup. 30-day soft-delete window. Versioning + change feed.
+ object storage · Cool tier +
+
+
Vault container
+
WORM-immutable 7yr. Snapshots, one-time promotes. Lifecycle to Archive at 30d.
+ object storage · Archive tier +
+
+
Sealed local
+
.SEALED.zip with DO-NOT-READ.txt sentinel + .gitignore. Agent searches skip it.
+ _sealed-brain-backups/ +
+
+
+ +
+
Guardrails
+
+
+
Kill switch
+
Touch a sentinel file. All billable scripts abort exit 99 until removed.
+ .qwen-killswitch +
+
+
Spend gate
+
Checks cloud month-to-date spend vs ceiling before any billable op. Fail-closed.
+ spend-gate.ps1 +
+
+
Cloud budget
+
Email alerts at 50% / 75% / 100% actual + 100% forecasted. Outside-in safety net.
+ provider budgets API +
+
+
+ +
+
Discipline
+
+
+
Audit-trail
+
Every session writes one row. Open / closed / locked status. Survives all compaction.
+ audit-trail.md +
+
+
Session journals
+
Per-session detail dossier. Concrete, dense, restorable. Archived when stale.
+ REVIVAL-*.md +
+
+
Fix-at-root reflex
+
Encoded rule: notice bug in shared infra → fix source first, never route around.
+ fix-at-root-reflex.md +
+
+
+ +
+
+ +
+

By the numbers

+
+
<$1
Azure Blob storage
+
7 yr
WORM retention
+
~3 KB
Cold-start brief
+
3
Independent fail-safes
+
+
+ +
+

Hardware reality

+

Honest version: the local-compute pillar carries weight, and "consumer GPU" hides a wide range. Here is what to expect at each profile. Everything else in Agent OS (memory tiers, vault, guardrails, audit-trail, continuity discipline) works on any machine that runs your editor.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProfileLocal modelDistill speedVerdict
Workstation, 16 GB+ VRAM
RTX 4080/5080/5090, M3/M4 Max, similar
14B coder model, full quality~3–15 sec / summaryReference-implementation experience.
Mid-range laptop, 8 GB VRAM
RTX 3060/4060, M2 Pro, etc.
7B coder model, q4 quantized~10–30 sec / summaryWorkable. Summaries shorter, slightly noisier.
Integrated graphics
no discrete GPU
3B model on CPU, or hosted small model~30–90 sec / summarySlow but functional. Or skip local entirely and use a cheap hosted model — the spend gate keeps it bounded.
Phone-class computeNot the target. The pattern needs some available compute for distillation.
+

The five non-compute pillars don't care about the GPU. If you can run an editor and reach object storage, you can run Memory + Vault + Guardrails + Brain backup + Continuity unchanged. Local compute is the cherry on top, not the load-bearing wall.

+
+ +
+

Scaling beyond one workstation: the networked brain

+

The pattern starts on a single workstation, but the semantic-brain pillar is designed to network. Run the brain as a containerized service exposing HTTP and Server-Sent Events, and any number of agents on any number of machines hit the same recall surface — no per-seat duplication of the corpus, no drift between team members, no re-embedding when a new agent joins.

+
+
+
Brain service
+
+
+
Frozen read collection
+
Curated corpus baked into the image at build time. Sealed vector segment, fast queries, deterministic across deploys. Restart-safe.
+ prebuilt-index/ in container +
+
+
Sidecar write collection
+
Lazily created at first write in the same persistent client. Holds new memories, ad-hoc corpus loads, per-agent remember() calls. Always writable.
+ side-collection · same DB file +
+
+
Merge at query time
+
Each recall() queries both collections in parallel, merges by distance, returns top-N. Caller never sees the seam.
+ recall.py merge layer +
+
+
+
+
Multi-agent
+
+
+
Shared HTTP/SSE
+
Multiple agents — same model or different — connect to one brain URL. Every remember by one agent is queryable by every other within seconds.
+ /sse · /tool/recall · /tool/remember +
+
+
Coordination primitives
+
Optional layer adds claim() / release() / handoff() / pulse_others() so agents don't step on each other on a shared task.
+ multi-agent coord wedge +
+
+
Audit-trail still wins
+
Even with a shared brain, the canonical decision log is the per-repo audit-trail. Brain is for fuzzy recall; audit-trail is for ground truth.
+ audit-trail.md (per workspace) +
+
+
+
+

This is how the same architecture scales from "one developer, one machine, one Copilot" to "a team of humans + agents working a multi-month codebase together" without redesigning anything below the brain layer.

+
+ +
+

How a session actually runs

+
+
    +
  1. Trigger. User types a routing keyword. Agent loads scoped memory, runs brain pulse, fetches latest revival doc.
  2. +
  3. Work. Edits, searches, runs commands, calls scripts. Branding stamp + version bump on every touched file.
  4. +
  5. Checkpoint. Every ~5 exchanges, brain checkpoint. Discoveries written to durable memory immediately, not "noted for later."
  6. +
  7. Touched-folder log. Anything outside the workspace gets registered so the next backup grabs it.
  8. +
  9. Close. Audit-trail row + REVIVAL doc + brain remember(). Session memory archived.
  10. +
  11. Overnight. Scheduled tasks run vault sync, weekly brain snapshot, and rolling-window memory archive — all gated by spend-gate.
  12. +
+
+
+ +
+

What it replaces

+
+
+

Default agent experience

+
    +
  • Cold start every chat. "Read the scrollback."
  • +
  • Auto-compaction picks what survives. Lossy by surprise.
  • +
  • Chat-only memory. Disk reality drifts from agent reality.
  • +
  • No cost ceiling. Bug in a loop = morning email from billing.
  • +
  • Backups are someone else's job.
  • +
  • Audit = scrollback search.
  • +
+
+
+

Agent OS

+
    +
  • Cold start reads a 3KB curated brief. Zero context loss.
  • +
  • Compaction can happen safely — durable memory survives it.
  • +
  • Memory tiers map to disk, vector brain, and immutable cloud.
  • +
  • Three-layer cost gate. Worst case = abort, never overspend.
  • +
  • Nightly azcopy + weekly brain snapshot + sealed local copy.
  • +
  • Audit-trail with one row per session. Always greppable.
  • +
+
+
+
+ +
+

How this fits next to existing tools

+

Plenty of good work exists in this space. Calling out the baselines so the contribution here is precise — Agent OS is the combination, not any one piece.

+
+
+
GitHub Copilot Chat memory
tiered memory · per workspace
+
The actual host platform behind the reference implementation. Provides the memory tiers Agent OS leans on. What's missing in the box: durable cold storage, cost gates, the discipline conventions, the local-model distillation.
+
+
+
Cursor · .cursorrules
project-scoped instructions
+
Solves preference persistence and routing. No durable journal, no audit trail, no cold-start protocol, no cost gates. Sits at the same tier as the routing rules in /memories/.
+
+
+
Cline / Roo Code
custom-instructions + agentic loops
+
Strong on agentic tool use. Memory is per-conversation. Same gap as default Copilot: no durable layer between conversations, no cost gate, no immutable audit.
+
+
+
Aider · .aider.chat.history
conversation log + git commits
+
Audit-as-git is excellent — every change is a commit. Closest existing analog to the audit-trail pillar. Doesn't have the brain, the vault, or the cost gates.
+
+
+
Continue.dev
configurable IDE assistant
+
Configurable model routing and context providers. Comparable to the routing layer. Memory and audit story is lighter; no cold-storage tier.
+
+
+
LangChain / LlamaIndex memory
programmatic memory abstractions
+
Library-level building blocks for memory. You'd assemble something like the memory + brain pillars on top of these. Doesn't speak to discipline conventions or cost gates — that's outside their scope.
+
+
+
AutoGen · CrewAI · smol-agents
multi-agent orchestration
+
Solves how agents coordinate during a session. Agent OS is concerned with what survives between sessions. Complementary, not competing — wire either of these on top of the brain layer for multi-agent.
+
+
+

What's distinctive here: the tiered-memory + WORM-vault + fail-closed cost gate + local-model distiller + networked brain — assembled and disciplined as one architecture, with conventions that keep the agent honest. Each individual pillar has prior art. The integration is the point.

+
+ +
+

Try the cold-start protocol

+

Three commands sketch the pattern. The agent reconstructs working state from durable artifacts — no scrollback dive, no host summary required:

+
# 1. Load routing rules + preferences (auto-loaded; this is the manual form)
+Get-Content /memories/00-routing.md
+
+# 2. Generate a curated cold-start brief — local model, ~60 sec, zero-cost
+pwsh tools/qwen-coldstart.ps1
+
+# 3. Read the latest session journal (compressed if >24h old)
+pwsh tools/latest-revival.ps1 -N 1
+

Paths shown are from the reference implementation. Equivalent flows compose easily on macOS / Linux / any shell.

+
+ +
+

Where this could matter

+

Long-running coding campaigns. When work spans weeks across many sessions and any detail loss costs hours of rediscovery.

+

Regulated environments. WORM-immutable audit trail with cryptographic time-based retention. Every session, every decision, every command — restorable for 7 years.

+

Multi-agent handoffs. When one agent finishes and a different model picks up. Curated brief + audit-trail + repo memory mean the receiving agent doesn't start cold.

+

Cost-sensitive autonomy. When the agent has authority over billable resources. Three-layer fail-closed cost gate plus outside-in budget alert means autonomy without surprise bills.

+
+ +
+
+
Reference implementation: VS Code + GitHub Copilot Chat + an object-storage backend + a local open-weights model on a consumer GPU. Not bound to any of these — swap freely.
+
License posture: open pattern. The whitepaper (this page) is shared freely; the reference implementation is permissively licensed. Attribution to Recall™ appreciated.
+
Recall™ trademark application pending. Use the ™ designation in any republication; switch to ® once the registration is granted.
+
Doc generated: 2026-05-07.
+
+
+ +
+ + From 029c7fb9b70c57c0a88de3c9d5473950559c2223 Mon Sep 17 00:00:00 2001 From: Steve Paltridge Date: Fri, 8 May 2026 03:06:59 -0600 Subject: [PATCH 2/2] Fix: ruff import sort in src/recall/transport/http.py (CI unblocker) --- src/recall/transport/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recall/transport/http.py b/src/recall/transport/http.py index f113cda..0094ac2 100644 --- a/src/recall/transport/http.py +++ b/src/recall/transport/http.py @@ -12,7 +12,7 @@ from starlette.requests import Request from starlette.responses import JSONResponse -from ..license import LicenseError, OSS_LICENSE, require_chunk_capacity, require_for_tool +from ..license import OSS_LICENSE, LicenseError, require_chunk_capacity, require_for_tool from ..store import is_ready from ..tools import TOOL_REGISTRY from ..tools.recall import _recall_structured