Decision memory (BYO)
When you build a fullstack app over multiple days, tsforge can remember product and architecture decisions (FK UX, naming, what already shipped) by talking to a memory backend you run. No vendor is bundled. Fresh tsforge in the same project loads the brief — you do not need --continue.
This is separate from Learning from past runs (Phase 1 failure→fix → TTSR). That channel stays local and automatic. Decision memory is opt-in context only: it never changes the gate.
Quick setup (HTTP / Hindsight)
Section titled “Quick setup (HTTP / Hindsight)”- Run a Hindsight-compatible API (example):
docker run -it --pull always --name hindsight -p 8888:8888 -p 9999:9999 \ -e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \ -v hindsight-data:/home/hindsight/.pg0 \ ghcr.io/vectorize-io/hindsight:latest- Add to
tsforge.config.jsonat the project root:
{ "providers": { "memory": { "kind": "http", "baseUrl": "http://localhost:8888" } }}Optional: set "bankId": "tsforge:github.com/acme/crm" to pin the bank. Otherwise tsforge derives it (see below).
-
Session A: build a feature with a non-obvious decision (“company FK is a native
<select>”). When the gate goes green — or a greenfield feature verifies — tsforge retains it. You should see a tool linedecision memory: retained to bank …(orretain failed …if the backend rejected the write). -
Session B (new terminal, same repo):
tsforgeagain. On start you should see eitherdecision memory: loaded brief for bank …ordecision memory: bank … ready (empty). An empty bank is still wired for retains — the write path is not dropped just because recall had nothing. -
Stop the backend and run again — the session still starts; there is simply no brief. The same holds for a backend that hangs rather than refusing: every memory call carries a 3s deadline and start-up is capped, so a sick backend cannot block the CLI. A slow recall times out the brief only; the provider stays attached so later green sends can still retain.
What gets sent
Section titled “What gets sent”Three curated channels (never the raw user prompt):
- Post-green extraction (default on) — after an interactive send goes green, tsforge asks the session model for durable product/architecture decisions from that turn and retains 0..N of them. Plan approvals, harness chatter, debugging, and one-off tasks yield nothing.
/remember <decision>— you explicitly park a decision in the bank.- Greenfield feature verified —
Feature verified: <id> — <description>.
Before anything is sent, a redaction pass drops lines that look like secrets (API_KEY=…, password: …, authorization: …) and rewrites every sk-… token.
To disable automatic post-green extraction (and rely on /remember + greenfield only):
{ "providers": { "memory": { "kind": "http", "baseUrl": "http://localhost:8888", "autoRetain": false } }}Legacy retainPrompts: false still opts out. Raw prompt retain is gone — retainPrompts: true is obsolete and ignored.
Treat the bank as untrusted input
Section titled “Treat the bank as untrusted input”Whatever recall returns is injected into the agent’s context inside a <project-decisions> block that marks it as reference data, never instructions. Bank contents are model-extracted and unreviewed, so anyone able to write to the bank — a teammate, another project sharing a bank id, a poisoned memory — would otherwise be writing straight into the highest-trust part of the prompt.
MCP variant
Section titled “MCP variant”{ "providers": { "memory": { "kind": "mcp", "server": "hindsight", "retainTool": "retain", "recallTool": "recall", "forgetTool": "forget" } }, "mcpServers": { "hindsight": { "command": "npx", "args": ["-y", "your-hindsight-mcp"] } }}Tool names default to retain / recall / forget. They are invoked as mcp__<server>__<tool> with bank_id and content / query.
Bank id (per project)
Section titled “Bank id (per project)”Computed each session — not read from .tsforge/:
providers.memory.bankIdif set- Else normalized
git remote get-url origin→tsforge:github.com/acme/crm - Else
tsforge:path:+ SHA-256 of the project root (directory that owns.gitortsforge.config.json)
Same remote on two machines shares one bank. /memory prints the resolved bank when configured.
What is stored
Section titled “What is stored”Curated decision text only (e.g. “Contact.companyId required; company FK is native select”). Not full chat, not file dumps. Obvious secrets (API_KEY=…, sk-…) are redacted before retain. HTTP retains use context tag tsforge-decision.
/memory and /remember
Section titled “/memory and /remember”In an interactive session:
/memory— coding lessons (Phase 1 TTSR ledger) + project decisions from the external provider/remember <decision>— retain one durable product/architecture decision now/memory forget— clear the local ledger and ask the provider to clear that bank
/memory prints the resolved bank id when configured.
Fail-soft
Section titled “Fail-soft”Backend down, bad config, or unknown kind → warn or skip; session and gate continue. Omit providers.memory → today’s behavior (Phase 1 only).
→ tsforge.config.json · MCP servers · Learning from past runs · Interactive CLI