This document explains what each released version delivered.
Product definition: PRODUCT.md. Planned work: ROADMAP.md. Destination narrative: README.
Goal: prove the system reduces re-explanation in technical work.
Delivered:
- local ingestion with normalized percepts;
- local extraction through Ollama with an offline heuristic fallback;
- selective review and confirmed-only context packs by default;
- sectioned context packs with judgment, decisions, constraints, tasks, preferences, facts/events and evidence;
- source qualification through trust, scope and confidentiality;
- explicit promotion, supersedence and contradiction lifecycle operations;
- memory quality metrics;
- expanded PII detection and optional local encryption;
- PostgreSQL + pgvector and zero-config SQLite backends;
- MCP, API, CLI and per-client MCP documentation;
- initial observer domain inference using keywords and graph signals;
- initial judgment profile.
Goal: close the loop between retrieving context and capturing what changed during real technical work.
Delivered:
- cognitive sessions with start, observe, complete and feedback over MCP, API and CLI;
- task-aware context packs (coding, architecture, debugging, writing, planning, review, meeting prep);
- first-class projects with repos, aliases, goals and session/percept linkage;
- product usefulness feedback and session/product metrics;
- multi-stage retrieval with graph expansion, firewall and source-trust weighting;
- fast and deep observer modes with domain/project/task uncertainty;
twin doctorandtwin setupfor ollama, postgres and MCP clients;- incremental developer sensors (Git, watch) preserving artifact ≠ percept ≠ memory.
Goal: keep memory quality, coherence and auditability as ingestion scales beyond manual curation.
Delivered:
- quality analyzer with neighborhood discovery, claim-aware findings and recomputable review priority (with conflict/privacy floors);
- Review workbench with priority queue, side-by-side diffs, keyboard shortcuts and batch preview/apply;
- transactional merge and split with compatibility gates, evidence mapping on split, provenance and full undo;
- artifact provenance chain via explicit artifact↔percept links (no content-hash cascade);
- source×type calibration and soft confidence adjustment at extraction;
- safe duplicate-group automation (single canonical survivor) and policy-gated task archival;
- retention and deletion propagation with tombstones and dry-run;
- isolated extraction/retrieval eval harness (firewall/consolidation evals scaffolded, not delivered);
- API, CLI and MCP surfaces for review, consolidation, provenance and evals;
- retrieval that excludes merged, split, archived, unsupported and stale memories by default.
Goal: make different LLMs apply a stable yet evolving model of how the user evaluates trade-offs — without confusing observed behavior with personal principle, and without silent identity changes.
Delivered:
- first-class
JudgmentItemtaxonomy (preference, belief, principle, value, heuristic, constraint) with confidence, strength, stability and typed scope; - canonical judgment store (SQLite/PostgreSQL) with YAML as bootstrap/export only;
- immutable
JudgmentRevisions; versions and snapshots point at revision IDs (restore clones history, never rewrites it); - proposal engine (
propose_from_memory/ demo pattern detector) — observation may propose, only the user constitutes; - state-aware preview tokens covering final payload, edits and supporting-memory fingerprints;
- all proposal actions (
create,updateas patch,weaken,strengthen,supersede,add_exception,deprecate) with transactional approve/versioning; - constitutional mutations require
confirm_constitutional, including when the target is already constitutional; - application engine with
JudgmentContext(domain, persona, project, audience, client, stage, conditions) and exception effects (disable,reduce_strength,replace_with,require_confirmation); - explainable
simulate/ counterfactual (evaluatewithout side effects); abstention when judgment signal is insufficient; - conflict detection that records open conflicts without deactivating active judgment;
- Twin-influenced evidence down-weighted; sessions that consumed judgment auto-mark extracted memories;
- structured applicable judgment section in context packs (not the full profile);
- CLI (
twin judgment …), HTTP API and MCP tools for proposals, applicable packs, simulate and approve; evals/judgment/fixtures for scope/precedence scenarios.
Goal: transform the domain firewall into contextual, verifiable governance independent of the main LLM.
Delivered:
- authorization context (
AccessRequest: principal, persona, purpose, audience, tool) shared across pack/session surfaces; - governance policy engine with precedence (constitutional deny, then deny, then grant/redact, then allow, else default-deny in restricted mode);
PrivacyDecisionaudit trail with per-resource effects and policy-set version references;- field/domain/ownership classification and ephemeral
RedactionPlantransforms (canonical store untouched); - temporary
PermissionGrants with TTL, max-uses and compare-and-set consumption; - prompt-injection quarantine before extraction (quarantined content cannot become memory/judgment);
- logical vault labels and employer-ownership policies (no work data to personal cloud);
- deletion preview/execute with lineage accounting; leakage canaries;
- context packs evaluate privacy after retrieval (deny/redact before assembly; evidence skipped for redacted items);
- sessions capture persona/purpose/tool and privacy decision ids;
- CLI (
twin privacy …) for simulate, explain, grants, quarantine and delete-preview; tests/privacy/test_engine.pycovering deny/redact/grant/quarantine/canary invariants.
Goal: capture operational knowledge from work through authorized, incremental connectors rather than manual exports alone.
Priority sources:
- GitHub repositories, commits, pull requests, issues and review discussions;
- Slack channels and threads;
- professional Gmail and Outlook;
- Calendar;
- Fireflies;
- Meetily;
- shared technical documents.
Each connector must preserve authorization, source ownership, incremental checkpoints, provenance, confidentiality and deletion behavior. Employer data should remain physically and cryptographically separable from personal data when policy requires it.
Delivered:
Phase 1 — Connector Framework:
- shared
ProfessionalConnectorcontract + adapter manifest/registry (with declaredauth_mode); no real providers yet; SourceAccount/ConnectorInstancewith declared ownership (personal | employer | client | opensource | shared | unknown), a mandatory owner principal, per-organization work vaults (ensure_org_vault) and preview-first, audited reclassification;CredentialStore(encrypted file, fail-closed — no crypto backend means no connector) with locked atomic writes and backup recovery; the DB keeps only acredential_ref, never the secret; provisioning is compensable andrevokeis resumable (revoked_with_residual_secretis reported, never claimed clean);- idempotent ingest spine:
RawConnectorItemto stagedConnectorRecordto quarantine gate toPercept, keyed byconnector:account:type:id:revision; the same revision with different content is arevision_collisiondead letter, never an overwrite, and persisted records are immutable (processing state lives in columns); - nothing becomes cognitively visible before a consistent commit: records, percepts, the committed batch and the CAS-versioned checkpoint land in one transaction; partial batches persist only raw items + dead letters; per-(connector, stream) leases keep concurrent workers out;
- edits (new revision, old retained); deletions resolve prior lineage into a
ConnectorDeletionEventfor the deletion planner; auth-expiry and rate-limit handling; sanitized persisted errors; dead-letter retry/replay from raw items; FakeConnectorproving the full path; CLI (twin connector …), REST (/api/connectors) and MCP tools, all gated byconnector:*capabilities. Confirmation model: the agent-facing MCP surface is preview/confirm with state-fingerprinted tokens (connector_sync), and ownership reclassification is state-fingerprinted on every surface; the authenticated HTTP API is otherwise a direct command surface for administrators — capability-gated, but without preview tokens;- per-(connector, stream) leases carry a monotonic fencing token, are renewed after every fetched page, and the finalize transaction re-asserts ownership — a worker that outlived its lease cannot publish results;
tests/connectors/test_service.py+tests/connectors/test_authz.pycontract suites (SQLite and Postgres) +evals/connectors/scenarios (normalization, replay, partial batch, revision collision, checkpoint failure, quarantine, source deletion). Connectors capture evidence; cognition still creates understanding — no connector path writes confirmed Memory or Judgment.
Phase 2 — GitHub Connector:
- REST v3 adapter (
twin/connectors/github/) over the Phase 1 framework:GitHubClient(Link-header pagination, per-stream page budget, rate-limit to structuredretry_afterthe scheduler respects), read-only PAT auth (awaiting_authwithout a token; write scopes detected viaX-OAuth-Scopesdegrade health with a least-privilege warning); - dynamic streams per repository —
repo:{owner}/{name}:{issues|pulls|commits|releases}from the new optionalplan_streams()protocol method — each with its own checkpoint/lease; incremental cursor is the provider'supdated_atwatermark re-fetched with a lookback window and deduplicated by revision; PRs are detected via thesince-capable issues listing, then re-fetched from/pullsas the authoritative object; - nine external types normalized to
ConnectorRecords (repository,issue,issue_comment,pull_request,review,review_comment,commit,release,check_summary) withgithub:{login}actor ids, a sharedthread_key/lineage_rootper issue/PR, and honest affordances (deletions: false— not observable via REST polling); - lifecycle-aware source trust (merged PR 0.95 > approved review 0.90 > commit 0.85 > body/release 0.80 > human comment 0.75 > check 0.70; bots 0.50 — below the review threshold, marked
derived=likely_notification); every PR lifecycle revision is retained so the merged state wins without erasing rejected alternatives, and the heuristic extractor now captures "decided against / instead of X use Y" as decisions carryingpayload.rejected_alternative; - per-source candidate policy at extraction (
twin/cognition/source_policy.py): GitHub proposes decisions/constraints/procedures/facts/events/tasks, never preferences or beliefs; tasks are born needing review; instances can narrow the policy viaconfiguration.ingestion_policy; - setup and backfill preview surfaces:
twin connector github repositories,twin connector backfill --preview/POST /api/connectors/{id}/backfill?preview=true/ MCPconnector_backfill_preview(capabilityconnector:backfill) — previews report scope, vault, policy and volume signals and never ingest; Phase 2 backfill itself is the first unwatermarked sync bounded byconfiguration.backfill_since(the partitionable BackfillJob is Phase 4); - optional webhook receiver
POST /api/webhooks/github/{connector_id}: HMAC-authenticated (X-Hub-Signature-256against a dedicated secret in the CredentialStore, uniform 401 on every failure), it only marks the sync state due with atargeted_streamshint the scheduler consumes — the payload never becomes canonical state and polling remains the authoritative reconciliation; tests/connectors/github/test_adapter.pycontract suite against an offline API double (tests/connectors/github/github_mock.py), a Postgres mirror test, andevals/connectors/scenariosgithub_pr_lifecycleandgithub_bot_lineage.
Phase 3 — Slack Connector:
- Web API adapter (
twin/connectors/slack/) over the Phase 1 framework:SlackClient(cursor pagination, per-stream page budget, rate-limit to structuredretry_after),auth_mode=slack_bot_tokenwith honest "privilege unverified via auth.test" health detail; read-only operation (no chat:write); - dynamic streams per allowlisted channel —
channel:{id}fromplan_streams()— each with its own checkpoint/lease; incremental cursor is the maximum observed Slack eventtsacross history roots and thread replies (not a pure history cursor) plus lookback; substreamshistorythenthreads; durable continuation when the page budget is exhausted; - activity on roots older than the lookback window is recovered via durable Events API hints (
pending_threads,pending_message_refreshes,pending_tombstones) — the webhook never becomes canonical content; each hint generation has anid(event_idor synthetic) so a fetch only consumes generations it observed; consumption uses commit-freeconsume_connector_sync_hints_casinside finalize (CAS conflict aborts the whole batch); - external types
channel/message/thread_replywith workspace-qualified ids (slack:{team_id}:{user},thread_key=slack:{team_id}:{channel}:{thread_ts}); edit revisions viaedited.ts+content hash; reply deletions preserveexternal_type=thread_replyfor lineage; file bytes are not fetched — messages may carryslack_fileartifact refs withdownload_status=metadata_only; - channel metadata revalidated via
conversations.infoeach sync (TTL cache, default 1h);channel_kindfails closed — stale metadata with a failed refresh never authorizes as public;include_private_channels/include_direct_messagesenforced at sync time; - conservative source trust (human root 0.70 / reply 0.65; bots 0.45 marked
derived=likely_notification, with GitHub-ref extraction); Slack source policy requires review for every allowed candidate type; - setup helpers:
twin connector slack channels, backfill preview, optional Events API webhookPOST /api/webhooks/slack/{connector_id}(HMACX-Slack-Signature, url_verification,event_iddedupe); tests/connectors/slack/test_adapter.pyagainsttests/connectors/slack/slack_mock.pyandevals/connectors/scenarioslack_thread_bot_lineage.
Phase 4 — Professional Email:
- shared cognitive mail layer (
twin/connectors/mail/): MIME split (authored/quoted/signature), HTML kept only asbody_html_untrusted_stub(never safe-to-render), source-heuristic classification, conservative trust, and oneConnectorRecordnormalizer (actor_ids= sender only;participant_ids= sender+to+cc;thread_key=mail:{provider}:{account}:{thread_id}); attachment mode is explicit (metadata_only/ discovery — bytes not downloaded by default); - Gmail adapter (
gmail.readonly): bootstrap capturesbootstrap_history_idbefore the time-range scan, then History catch-up sealshistory_id(no gap for concurrent arrivals); label removal tombs only when no allowlisted label remains; tombstones resolvethread_messagevsmessage; - Outlook/Graph adapter (
Mail.Read): continuous sync bootstraps via delta enumeration (allvalues processed, never discarded);@removed/changedresolves current folder membership before global tombstone; attachment discovery + shared nextLink/deltaLink error decoder; - partitionable
BackfillJob:SyncExecutionContextbounds; namespaced streams; per-stream partition progress; claim CAS + finalize fence + heartbeat renew (stale workers cannot publish); completes only when every stream isdone; - email source policy stricter than Slack; notifications marked
derived=likely_notification; tests/connectors/gmail/test_adapter.py+tests/connectors/outlook/test_adapter.py+tests/connectors/mail/test_normalize.pyand evalgmail_thread_lineage.
Phase 5 — Calendar and meetings:
- shared meeting cognitive layer (
twin/connectors/meeting/): provider-agnosticMeetingRecord/TranscriptSegment/SpeakerIdentity; speaker mapping with explicit confidence (never auto-mergeSpeaker N); account-scoped speaker ids;actor_ids= speakers who spoke at ≥0.70 confidence (silent attendees stay inparticipant_idsonly); calendar↔meeting correlation viacalendar_event_id/iCalUID/conference_url/correlation_fingerprinton metadata + artifact_refs (no WorkEpisode yet); - long transcripts emit
meeting_manifest+meeting_transcript_chunkrecords (segment-aligned chunking — never silent truncation); provider summary is a separate derived record with its own content hash revision; - Calendar adapter (Google Calendar v3, read-only): calendar-qualified event ids (
google_calendar:{calendar_id}:{event_id}); allowlist (empty meansawaiting_configuration);updatedwatermark + lookback; cancelled to tombstone;freebusy_onlyredacts the persisted raw payload (not only record content); paginated calendarList discovery;max_pages_per_streamhonored; - Fireflies adapter talks real GraphQL (
POST https://api.fireflies.ai/graphql); streammeetings;creation_watermarkis meeting-creation only (fromDate), not update time — incomplete IDs stay in durablepending_transcriptsand are re-fetched by ID until terminal; recent completes are periodically reconciled for late edits; pageskipadvances with overlap; processing/live/partial marked incomplete; chunk/summary shrinks emit tombstones; recording artifact id is the transcript id (signed media URLs are not persisted); deletion feed not offered by provider (deletions=false— retain until offboarding/reconcile); - source policies require review for every allowed candidate type; scheduler intervals
calendar: 15m,fireflies: 30m; - setup helpers:
twin connector calendar calendars,twin connector fireflies meetings; tests/connectors/calendar/test_adapter.py+tests/connectors/fireflies/test_adapter.py+tests/connectors/meeting/test_normalize.pyand evalcalendar_meeting_correlation.
Phase 6 — Shared documents:
- shared document cognitive layer (
twin/connectors/documents/): provider-agnosticDocumentRecord/DocumentRevision+DocumentProviderprotocol for future Drive / OneDrive / Notion; long bodies emitdocument_manifest+document_revision_chunk(heading/paragraph/line chunking — never silent truncation); oversized files (max_file_bytes) emit metadata-only manifests (content_available=false,evidence_role=artifact_metadata); decode-lossy content isoperational+requires_review; prior revisions remain addressable after edits; - document identity for the folder adapter is path-stable, not rename-stable (rename = delete + create unless a future correlator links them);
- authorship: email to
mail:{email}actors; plain front-matter names stay account-scopedauthor_labelmetadata (confidence 0.30) and are never auto-promoted to global person ids; - local folder adapter (
twin/connectors/folder/): explicit watch roots (empty meansawaiting_configuration); duplicate root ids and overlapping roots fail closed (allow_overlapping_roots=trueto permit); include/exclude globs (defaults: md/markdown/txt/rst — json/yaml recognized as text only when included); full scan each sync (content-hash skips unchanged files;max_pages_per_streamis not a work budget); checkpointknown_filescapped bymax_known_files(default 50k); deletes / chunk shrinks to tombstones;auth_mode=none; symlinks rejected by default (follow_symlinks=truerequires target inside the same root); POSIX permission bits inspected (Windows topermission_inspection=not_evaluated); - source policy requires review for decision/constraint/procedure/fact/task; scheduler interval
folder: 5m; - setup helper:
twin connector folder roots; tests/connectors/folder/test_adapter.py+tests/connectors/documents/test_normalize.pyand evalfolder_document_revisions.
Phase 7 — Cross-source cognition:
- cognitive correlation layer (
twin/cognition/correlation/):ExternalIdentity/IdentityLink,ProjectLink,WorkEpisode/EpisodeLink— connectors still only capture evidence; correlation proposes structure, never confirmed Memory or Judgment; - vault partition: every correlation pass clusters per
vault_id; anchors andcorrelation_keyare vault-qualified — no WorkEpisode / IdentityLink / finding may mix vaults without explicit cross-domain action; - episode identity: idempotent via
correlation_key+episode_anchors(lineage, calendar id, fingerprint, thread) — repeated passes attach sources, do not duplicate episodes; - reconciliation: EpisodeLinks carry
active|removedlifecycle; tombstones drop membership and rebuild participants / dates / source_refs / confidence from active links only (max(active EpisodeLink.confidence); empty toclosed+ 0.0) — still not full multi-factor scoring; - independence: per-
EpisodeLinkindependence_group+directness(episode keeps aggregate count / primary lineage); derived notifications/summaries do not inflate corroboration; - identity: upsert from actor ids within the same vault; email to candidate links only inside a vault; never merge by display name; cross-vault confirm refused without explicit flag; confirm / unconfirm / reject with
ExternalIdentity.confirmedcleared when no confirmed edges remain; - project mapping: exact
Project.repos/ aliases becomeProjectLinkwith lifecyclecandidate | confirmed | historical | rejected(confirmedbool kept as mirror); soft hint matches stay candidates;historical/rejectednever attachepisode.project_idand block auto-recreating a fresh candidate for the same container; - clustering: merge anchors (lineage, PR/issue refs, calendar ids) form components; fingerprint / thread are contextual (attach or candidate-only, no transitive overmerge of distinct merge components); soft temporal co-occurrence alone does not merge;
- conflict findings: true cross-source only (distinct sources must disagree); idempotent via
finding_key(reuse / supersede / close); never auto-resolved; - explainability CLI (read-only):
twin episode explain,twin identity why,twin project explainover anchors / links / findings already stored; - CLI:
twin correlate,twin episode list|show|explain,twin identity list|links|confirm|unconfirm|reject|why,twin project link|links|confirm|reject|historical|explain; tests/cognition/correlation/test_service.py,tests/cognition/correlation/test_lifecycle.py, and evalcross_source_work_episode.
Still deferred to Correlation depth (remainder in 1.3.x / 1.4 — not a Phase 10 blocker): multi-factor confidence, identity graphs + Entity resolution, HTTP/MCP explain APIs, scale/replay evals.
Phase 8 — Native proof:
- one host-native adapter: Claude Code Hooks (
twin/interfaces/native/claude_code/) — observes session start, user messages, tool request/completion, file/project context, session end; does not assemble Context Packs or create a parallel memory store; HostSessionBinding(hsb_…) links(host_type, external_session_id, occurrence)↔CognitiveSession; after Stop, the same external id opens occurrence N+1 (history preserved); cwd never identifies a conversation — missing session id is rejected;- security freeze: domain / project / persona / purpose / audience / vault captured at bind; refresh cannot widen scope silently;
- observations are idempotent only with a trustworthy id (
event_id/delivery_id/tool_call_id+phase/sequence); equal text alone never collapses events; only UNIQUE/PRIMARY KEY conflicts map toduplicated(never generic IntegrityError / NOT NULL / FK / CHECK); - concurrent SessionStart: unique binding wins; loser abandons its orphan
CognitiveSessionand returns the winner; - tool inputs pass redaction; unknown hooks become
unsupported_host_event(never forgeduser_message);transcript_pathbecomestranscript:{hash}identity; - fail-open hooks: Twin failures return
ok=false+error_id(no traceback on stdout) and exit 0 with--fail-open; stderr/logger hold diagnostics; Context Pack only for SessionStart/pack_request; - orphan policy: Stop without binding is a no-op; observations without / after an active binding are rejected; duplicate SessionStart reuses the open binding;
InterventionRecommendationis a display-only possible decision reversal cue (heuristic; may false-positive) — no host interruption/action in v0.6;HostCapabilitiesdeclare what Claude Code can accept;- MCP remains simultaneous:
native_bindings/native_session_statusexpose the same Sessions/Projects/Memories; native path never confirms Memory; - CLI:
twin native install|event|bindings;tests/interfaces/native/test_service.pyand evalevals/native.
Phase 9 — Evals and operations:
- connector observability (§58): durable
*_totalcounters onConnectorSyncState, applied exactly once perbatch.idviaconnector_counter_batchesledger — claim + bump share onestore.transaction()(claim never commits alone);reconcile_connector_countersrecovers crash undercounts and can repair divergence with audit; summary metrics separated from high-cardinalityinstances_detail;connector_percepts_totalcounts Percepts (not Memory candidates); nested undertwin stats/GET /api/metrics; - health snapshot (§57):
lag_seconds≡schedule_lag_seconds(max(0, now - next_run_at),nullwhen unscheduled);checkpoint_age_secondsand optionalsource_lag_secondsare separate; never-run connectors reporthealth=unknown;pending_itemscounts DLQ + backlog queues only (nottargeted_streamsscope); - setup plan (§77):
twin connector setup <type> --source-owner …prints ownership, authenticate, scope, preview, confirm (never ingests) and surfaces ownership/vault/org warnings; backfill preview remains the historical import gate; - scheduler ops:
twin connector due/twin connector sync-due;twin doctorresolves credentials (ref must decrypt), classifies due by schedule grace, and reports unhealthy / lagged instances; - §88 contract matrix: evidence-based cells (
pass|fail|not_supported|not_applicable|not_tested|partial|framework_only) with test pointers; framework Fake proof is a separate layer and never auto-passes real adapters;okfails closed on requirednot_tested/fail/partial; tests/connectors/test_ops.pyand evalops_health_metrics; per-adapter behavioural suites remain the real proof.
Phase 10 — Final Review:
- attests §93 Critérios de conclusão via evidence-based
completion_matrix()(twin/connectors/completion.py) — criteria cells carry test/eval pointers;passwithout evidence demoted;okfails closed onfail/not_tested/partial; - behavioural proofs live with their modules: lifecycle supersede after meeting candidate (
tests/memory/test_lifecycle.py); authorized work pack (tests/privacy/test_engine.py); completion matrix mechanics (tests/connectors/test_completion.py); - CLI:
twin connector completion(exit 1 when matrix not ok); - documents §94 out-of-scope and §95 thesis alongside the matrix payload;
- eval
connector_completion.
v0.6 is complete when twin connector completion reports ok: true and the connector/correlation/native suites remain green. Correlation depth remainder (multi-factor confidence, identity graphs, HTTP/MCP explain, scale evals) stays deferred to 1.3.x / 1.4 — not a Phase 10 blocker.
Goal: ensure that meaning is identified and catalogued by a cognitive interpreter rather than inferred from shallow lexical patterns.
Connectors and sensors already normalize heterogeneous sources into Percepts while preserving provenance, ownership, confidentiality and lineage. This version strengthens the next boundary: cognition must interpret what a Percept means before proposing any change to memory. The interpreter may use source metadata, session context, project context, participants and related evidence; deterministic code remains responsible for authorization, quarantine, confidentiality floors, provenance, persistence integrity, idempotency and review policy. Lexical rules may support routing and detection signals, but must not independently establish semantic memory types, domains, entities or cognitive confidence. A Percept that has not been interpreted remains pending or deferred — never “understood” merely because a model was temporarily unavailable.
Delivered:
- a cognitive interpreter (
twin/cognition/interpreter/) as the production path: the local LLM reads a Percept and emits grounded, act-awareInterpretedItems — each with a cognitive act (statement, question, hypothesis, proposal, decision, opinion, third-party claim), a memory type (including rejected alternatives), a speaker/attribution, and a verbatimevidence_span; items the model cannot ground in the source are dropped rather than stored; - deferral as a first-class outcome: in interpreting modes (
auto/ollama) an unavailable or failing model records the Percept asdeferred(orerror) and catalogues nothing — lexical rules never fabricate cognitive conclusions in the production path. Apercept_interpretationsrecord tracks execution status, model, prompt and schema versions and attempt count, so never interpreted, interpreted and empty, and deferred are three distinct, non-conflated states;extract_pendingselects by interpretation state, so a returning model resumes cleanly and settled Percepts are never re-interpreted (bounded retries viaMAX_INTERPRETATION_ATTEMPTS); - cognitive-act governance: a proposal is not a decision, and a question, hypothesis, opinion or third-party claim is born needing review regardless of the classifier's confidence; deterministic gates (quarantine, source policy, confidentiality floor, dedupe, calibration, review) still run exactly as before — the interpreter decides meaning, deterministic code decides use;
- lexical rules are detection-only:
heuristicmode recordsDetectionSignals (routing/prioritization hints — a candidate category and the source span) and creates noMemoryItemat all; establishing a memory type, domain, entity, confidence or evidence is the interpreter's job alone, and no offline path derives those from the text. The deterministic CI stand-in is anechomock (the counterpart of the hash embedder): it grounds content as neutral, review-boundfact/statementobservations with fixed confidence and makes no classification — any test that asserts meaning supplies authored ground truth (a recorded interpretation viaset_interpreter_override), never a lexically-derived one.TWIN_EXTRACTORis honoured at Config construction; - evidence is validated deterministically: every catalogued item's
evidence_spanmust appear verbatim (Unicode/quote/whitespace-normalized, no paraphrase) in the masked text the interpreter read — an invented span, even a non-empty one, is dropped, closing the hallucinated-evidence path; validation runs against masked text so PII placeholders line up and removed PII cannot return; - a service outage is separated from a Percept-specific failure: availability and the HTTP client are resolved once per batch by an
InterpretationRuntime; adeferred/unavailableoutage never consumes a Percept's retry budget and is never abandoned, while a reachable-but-failing interpreter is anerrorwith a failure class (transient/schema/permanent) bounded byMAX_INTERPRETATION_ATTEMPTSandnext_attempt_atbackoff before going terminal; - no silent semantic fallbacks: an out-of-vocabulary memory type is dropped (never coerced to
fact); an unrecognized domain becomesunknownand is routed to review (never silentlytechnical); a speaker attribution is grounded against the Percept's known actors — an unknown speaker is flaggedattribution_unresolvedand an unverified owner claimowner_claim_unverified, both review-bound; - quarantine is recorded as a pipeline/governance terminal with
interpretation_attempted = false, not as an "interpretation"; per-stage counters (emitted / grounded / ungrounded / policy-dropped / deduplicated / inserted / review-bound / invalid) are persisted for observability; - surfaces:
twin extractreports deferrals,twin interpret status/deferred/signalsinspect the queue and detection hints, andPOST /api/extractreturnsdeferred/interpretation_status/unresolved_references; tests/cognition/test_interpreter.py(deferral, outage-never-abandons, poison-input bounded, grounding incl. invented/paraphrase/masked-source, invalid type/domain, attribution) andtest_heuristic.py(heuristic never creates a memory; the echo mock classifies nothing), a Postgres mirror test,evals/interpretation/contract scenarios driven by authored interpretations (no model/network in CI), and an optionalevals/interpretation_model/layer that scores the real local model (act classification, type precision, attribution, evidence literality, invented-item rate) — skipped unlessTWIN_EVAL_MODEL=1. Connectors and sensors still capture evidence; the interpreter now creates the understanding, and no interpretation path writes confirmed Memory or Judgment on its own.
Goal: move from an on-demand observer toward a continuously updated extended-memory process inspired by the Global Workspace model. Natural consumer of Correlation depth: incremental correlation and episode-phase updates feed consolidation without full rescans.
Delivered:
- Workspace and consolidation spine for future continuous execution — synchronous, invocable evaluation (
workspace_tick) and windowed maintenance (run_consolidation_cycle), not yet a background worker/queue. Continuous / event-driven parallelism remains deferred. workspace_tick(twin/cognition/workspace.py) — stagesreading, observe, salience, recall, optional parallel_interpretation, done; preserves observer retrieval score separately from memory confidence; optional interpretation only forinput_mode=delta(snapshots do not invent deltas); refuses to interpret while domain is unclassified (never coerces totechnical);- identity / idempotency — durable
workspace_tickskeyed byidempotency_key,session_id+sequence, orsession_id+content_hashfor delta interpretation; repeated completed calls return the tick (duplicated=True); concurrentrunningreturnsblocked_concurrentwithout executing; failed ticks persisterror/error_stageand requireretry=Truewith atomic CAS (error to running) so only one reclaimer executes; Percept id is persisted immediately and reused on retry; - confidence + relevance recall (
twin/cognition/recall.py) — eligibility = confidence gate AND retrieval score gate; novelty may reorder eligible suggestions but cannot clear the relevance bar; firewallblockedstays ids/reasons only; - salience / novelty / contradiction cues (
twin/cognition/salience.py) — salience excludes novelty; novelty is ranking/inspection only; - daily / weekly consolidation (
twin/cognition/consolidation_cycle.py) — logical windows with durableconsolidation_runs(unique apply per window); concurrentrunningblocked;errorrequiresretry=Truewith atomic CAS reclaim; confirmed Memory/Judgment invariant raisesConsolidationInvariantError(run markederror, nevercompleted); - surfaces:
twin workspace tick(--input-mode,--sequence,--idempotency-key),twin consolidate daily|weekly,POST /api/workspace/tick,POST /api/consolidate/{daily|weekly}, MCPworkspace_tick/consolidate_cycle, nativeintervene_checksoft recall infos; tests/cognition/test_recall.py,test_workspace.py,test_consolidation_cycle.py, and offlineevals/consolidation/(including score-vs-confidence and confirmed-set invariants).
Goal: harden Twin from the v0.8 workspace/consolidation spine into a durable, auditable Personal Cognitive OS path — runtime, sessions, memory formation, packs, attention, connector readiness, sovereignty and release gates — without yet calling the product v1.0.
Delivered:
Phase 1 — Durable Cognitive Runtime:
twin-runtime/twin runtime start— durable background process with local scheduler + worker pool; not an autonomous agent (handlers call the same cognitive core as CLI/MCP/API);- durable job queue (
runtime_jobs) with priority, vault isolation, causal parent, idempotency keys,not_beforebackoff; - exclusive CAS claim + worker leases + heartbeat + dead-worker reclaim (expired
runningleases); - retries with backoff, dead-letter queue, cancel, explicit retry; model-unavailable failures never dead-letter model-gated kinds;
- initial job kinds:
interpret_percept,workspace_tick,consolidate_daily/consolidate_weekly,reembed_memory,integrity_check,connector_reconcile; - surfaces:
twin runtime {start,status,schedule,enqueue,job,retry,cancel},POST/GET /api/runtime/jobs…,GET /api/runtime/health, entrypointtwin-runtime; tests/runtime/test_runtime.py— exclusive claim, lease recovery, idempotent enqueue/schedule, vault isolation, DLQ, worker execution.
Phase 2 — Cognitive Sessions:
- lifecycle statuses:
active/paused/completed/abandoned/archived; - ordered
session_events(deltas) with gap detection; checkpoints; structuredSessionClosure(never auto-confirms Memory/Judgment); - pause / resume / reopen / archive; continuity via
external_session_idon events across tools; - surfaces:
POST /api/sessions/{id}/{events,checkpoint,close,reopen,pause,resume},GET …/closure; tests/cognition/test_session_lifecycle.py.
Phase 3 — Memory Formation:
twin/memory/formation.py— deterministicformation_identity/mem_f…ids; propose-or-corroborate; formation states (candidatetocorroborating/conflicting/awaiting_reviewtoconfirmed/rejected/ …); per-type policy (belief/procedure always review; never auto-confirm);- confirm requires evidence; reject requires reason; restore rejected back to re-review; auditable
MemoryOperations; explain view; - pipeline inserts via
propose_or_corroborate(idempotent on identity); - surfaces:
GET/POST /api/memory/candidates…,GET /api/memory/{id}/explain|history; tests/memory/test_formation.py.
Phase 4 — Consolidation Engine:
- operational stages on the existing cycle:
closed_sessions,open_tasks,review_prepare,change_report(+ weekly judgment proposals unchanged); - auditable
cognitive_change_report(counts + low-confidence inventory); review backlog stampsformation_state=awaiting_review; - still never confirms Memory/Judgment; window apply remains idempotent (
duplicated=Truereplays the same report); tests/cognition/test_consolidation_cycle.pycovers operational stages + replay.
Phase 5 — Judgment and Personas:
- durable
PersonaRecord(privacy_personas) bootstrapped with configurable starter personas;resolve_accessintersects persona domains/vaults/capabilities with principal∩binding (never amplifies); POST /api/judgment/versions/{id}/restore,GET /api/judgment/snapshots/{id}/explain,GET /api/personas;tests/privacy/test_personas.py.
Phase 6 — Mature Context Packs:
- structured pack metadata:
active,uncertainty,provenance_summary,token_budget,blocked_count,explanation; - modes:
compact/explainable/references_only; cognitive-act labels; dedupe + type diversity; pack-time prompt-injection screen; POST /api/context_packacceptsmode,session_id,request_scope;tests/cognition/test_context_pack.pycovers modes + injection exclusion.
Phase 7 — Attention + MCP runtime surfaces:
twin/cognition/attention.py— working-memory window, expected_value policy, typed outcomes, cooldown/cap/dedupe/suppress; default silence;attention_emissionsledger;append_session_deltaenqueuesattention_evaluateruntime job;- surfaces:
GET /api/sessions/{id}/attention,POST /api/attention/{id}/feedback, MCPget_context_pack,append_session_delta,get_attention,provide_feedback,capabilities,health; tests/cognition/test_attention.py.
Phase 8 — Professional Connectors production-ready:
- GitHub + Slack closed on §88 contract (collision DLQ, partial batch, quarantine, unauthorized, unknown schema);
production_ready_adapters()+twin connector production-readyattest ≥2 real adapters (Fake never counts);- runtime
connector_reconcileruns due syncs viasync_due(recovery path, not a stub inventory); tests/connectors/test_production_ready.py+ adapter contract gap tests.
Phase 9 — Data Sovereignty spine:
twin/sovereignty/— NDJSON export bundle + manifest checksums;create_backupcopies SQLite;validate_backup/restore_sqlite_backupto isolated path;- integrity checks (confirmed-without-evidence, orphan evidence) via runtime
integrity_check+GET /api/health/cognition; - surfaces:
twin backup {create,validate,restore},POST /api/backup,POST /api/backup/validate,POST /api/restore; tests/sovereignty/test_backup.py.
Phase 10 — Reliability and Evals spine:
- golden work loop (
twin.evals.golden/twin eval golden) — session, candidate, confirm, recall; injection never auto-confirms; - fail-closed
v1_completion_matrix()+twin eval v1-completion; - adversarial checks: prompt-injection detection + cross-domain recall deny;
evals/v1/cases/golden_work_loop.json,tests/evals/test_golden_work_loop.py,tests/evals/test_security_adversarial.py,tests/evals/test_v1_completion.py.
v0.9 is complete when the durability, formation, pack, attention, sovereignty and eval spines are green and GitHub + Slack attest production-ready. The v1.0 cut packages that spine as the daily-usable Personal Cognitive OS bar.
Goal: a trustworthy, daily-usable cognitive substrate — closed sessions, evidence-grounded memory, evolving judgment with human control, persona-aware privacy, mature MCP/connectors, export/backup/recovery, and measurable reduction in re-explanation. Not a complete autonomous mind. Built on the v0.9 Cognitive OS Spine.
Delivered:
- closed cognitive sessions across tools;
- reliable cognitive interpretation, memory formation and consolidation;
- evolving judgment with human control;
- persona-aware privacy and auditability;
- mature MCP interoperability and professional connectors (GitHub + Slack production-ready attestation);
- parallel observation and controlled consolidation;
- export, backup, deletion and recovery;
- durable cognitive runtime (
twin-runtime) with leases, DLQ and vault isolation; - release gates:
twin eval v1-completion,twin connector production-ready,twin eval golden; - package/
__version__to1.0.0; - threat model (ARCHITECTURE.md) and operator runbook (OPERATIONS.md).
Out of scope for v1.0:
- Multi-tenant SaaS isolation
- Formal methods proofs
- Hardware-backed secret enclaves
- Guaranteeing LLM non-hallucination (mitigated by evidence + human confirm)
Follow-on (not blocking v1.0): remaining adapter contract rows, unified explain UX, encrypted/incremental backups, soak/stress harness, re-explanation KPI dashboard.
Goal: make Twin easier to install, configure and trust day-to-day — guided setup, mainstream chat providers, clearer product docs and a friendlier local UI — without changing the cognitive core.
Delivered:
- guided
twin init/ setup wizard for Ollama (recommended), OpenAI-compatible, Anthropic and Gemini; - pluggable chat LLM adapter with presets (
ollama,anthropic/claude,gemini/google,openai,groq,openrouter,lmstudio,vllm, …); - embeddings via Ollama, OpenAI-compatible, Gemini or hash; Anthropic chat pairs with a separate embed backend;
- env keys honored per provider (
ANTHROPIC_API_KEY,GEMINI_API_KEY,OPENAI_API_KEY, …) plusTWIN_LLM_*/TWIN_EMBED_*; twin doctorprovider-aware checks; Ollama base URL resolution respectsTWIN_OLLAMA_URL/ configured home env (WSL-friendly);- CLI UX polish: review single-key actions, extract progress/ETA,
--auto-approve/-A, clearer panels and contrast; twin serveReview workbench refresh — candidate/neighbor cards, evidence quotes, flags, friendly labels;- Search / Pack / Memories: human-readable selects and metadata chips (implementation ids stay on CLI/MCP/API);
- Search relevance as relative % (top hit = 100%) with match-why chips under the score bar; Memories hides duplicate body when title equals summary;
- marketing README with banner / vision / before-after visuals; deep material under
docs/(FOUNDATIONS,PRODUCT,ROADMAP,CHANGELOG,ARCHITECTURE,CONNECTION,SETUP,OPERATIONS); - MCP client guides folded into INTERFACES; operator runbook moved to OPERATIONS; threat model moved to ARCHITECTURE; release history moved to CHANGELOG; future majors moved to ROADMAP;
- root
LICENSE(MIT); package/__version__to1.1.0.
Goal: make Claude Code's native path match a real chat lifecycle, make session/observer domain resolution evidence-based instead of keyword-fragile, harden the host contract so capabilities and identity actually gate behavior, and finish the host/CLI DX started in v1.1 — without changing the cognitive core's Memory / Judgment contracts.
Delivered:
twin native installmerges Twin hooks into~/.claude/settings.jsonby default (keeps non-Twin hooks;--no-merge/--settingsescape hatches;.twin-bakbackup on patch); event name comes from stdinhook_event_name, not a fake env var;- observation profiles:
twin native install --profile minimal|standard|verbosescopes which hooks are wired (lifecycle only →+PostToolUsedefault →+PreToolUse); twin native uninstallremoves only Twin-owned handlers (keeps third-party hooks);--restore-backuprestores the most recent.twin-bak;- context packs return as Claude's
hookSpecificOutput.additionalContext(observation hooks stay silent on stdout); - lifecycle fix: Claude's Stop is end-of-turn only (
assistant_result— binding stays open); SessionEnd closes the binding immediately and enqueues backgroundsession_complete(summary + extract viatwin-runtime) — default install wiresSessionEndwith per-hook timeouts (120s SessionStart / UserPromptSubmit / SessionEnd); - deferred context pack: SessionStart with no prompt text opens
unclassified(empty pack); the firstUserPromptSubmitthat search-votes a domain upgrades once and emits the pack — never waits on the local LLM in the hook; - host capabilities on
session_startgate real behavior: where a pack may surface, turn/session-end contract breaches fail closed, and intervention LLM calls respectdisplay_intervention; - stable install identity on bindings for provenance (derived from Twin home + host + user home — never a raw path); pack assembly deadlines abort stage-by-stage and mark skipped packs pending for the next injection-capable turn;
- documented native adapter checklist + identity tuple; fake-host evals cover lifecycle, security, capabilities and budget.
- hot-path session domain is search-vote only (keyword/graph guess removed); inconclusive make it stay
unclassifiedand enqueue backgroundsession_domain_resolve(multi-message LLM) or wait for client/MCP explicit domain; - Memory Observer no longer invents the consumer domain from text: uses the frozen session domain or an explicit argument (else
unclassified→ default-deny), with a soft same-domain ranking boost on hybrid search; session_summaryconsolidation folds dialogue plus deliberate observations (file/commit/doc/note/ host file/project context) with human speaker labels (User:/Assistant:…) so machine kind tags do not leak into evidence quotes; tool I/O,turn_completed, and session boilerplate stay on the session for replay;- native auth uses
surface=native+ hostclientwith allowlist toolnative-host(not CLI masquerade); provider Stop maps to structuralturn_completed(no[turn_end]text); background domain resolve markspending_context_packfor the next injection-capable event. - interpreter prompt/schema (interpret-v2) require
titleandsummaryso grounded items are no longer dropped as malformed; - CLI DX: human-readable views across connector and day-to-day commands, with a uniform
--jsonescape hatch for scripting (machine protocol surfaces —twin native event,twin mcp,twin serve— unchanged); - runtime CLI documents
session_domain_resolve/session_completejob kinds (twin runtime enqueue|status|job|retry|…; see INTERFACES + OPERATIONS); twin runtime start/twin-runtimeshow a live processing panel on TTY (in-flight workers, queue depth, recent jobs;--no-live/TWIN_RUNTIME_NO_LIVEescape hatch);twin doctorreports runtime queue backlog (pending / failed / dead-letter) from the store instead of pretending a worker is up;- connector historical backfill runs as background runtime jobs;
twin connector backfill --runenqueues and watches with progress/ETA (requirestwin runtime start); - MCP host identity is process-env only (
TWIN_MCP_CLIENT/TWIN_MCP_CLIENT_TOKEN);twin setup mcp <client>provisions credentials into the host env block — tools no longer accept client tokens as arguments; - drop versioned completion gates and phase folklore (
twin eval v1-completion/ connector completion matrices → behavior tests andtwin connector contract/ production-ready report); - docs/README polish:
CONNECTION.md→INTERFACES.md, ROADMAP for future majors, CHANGELOG as release history, clearer how-to-use and visuals; - package/
__version__to1.2.0.
Goal: deepen WorkEpisode from a flat cluster into an explainable, multi-sense arc and synthesize cross-source trajectory claims — with semantics driven by an LLM (not lexical rules), human gates before Memory/Judgment, and clearer review/docs surfaces so people can act on what the pipeline proposes. Course-corrected mid-cycle: phase/edge/reflect heuristics were replaced by a cognition pipeline whose stages are named for their brain analogy.
Delivered:
twin/cognition/episode_pipeline.py— brain-staged cognition chain (sensory → amygdala → basal → hippocampus_bind → cortex → hippocampus_consolidate → prefrontal) returning aCognitionReportwith per-stageok | deferred | blocked | skipped+ counts; mirrors the interpreter's deferral so a missing model never falls back to lexical rules andextractor=heuristicblocks the semantic stages;- LLM stages:
amygdalaclassifies member role + salience (classify_prompt),cortexproposes phases + narrative edges (understand_prompt),hippocampus_consolidatereflects the arc into trajectory candidates; phases/edges carryprovenance.method=llm+brain_stage; tests inject deterministic stage overrides (set_stage_override) as the golden pivot; - removed the semantic regex from
phases.py/edges.pyand thestructural_reflectorproduction fallback — the sensory scaffold keeps only ID-anchor / exact-match structure; phases/edges are built bycortex, never during structural correlation; EpisodePhasearc (goal → decision → execution → outcome) built from model-assigned roles (a decision pivot stays two decision phases); revisableEpisodeEdges (motivated | superseded | resolved | continues | contradicts) with humanconfirm/rejectsurviving cortex rebuilds; edges never alone create Memory;- incremental correlation:
correlation_dirtyindex drivestwin correlate --incremental; full rebuild (--full) remains the correctness oracle;--until <stage>stops after any sensory…cortex stage; - cross-sense soft-fuse links Slack↔GitHub request→PR trajectories when distinctive lexical overlap exists inside a time window (never fuse on project+time alone); ACC diversify keeps multi-source evidence from crowding out a single sense;
twin episode reflectsynthesizes trajectory MemoryCandidates only (needs_review=True,review_reason=episode_reflect,brain_stage=hippocampus_consolidate);valid_fromtracks the decision phase; idempotent via formation identity; defers when the model is unavailable;- reflect brief pulls related confirmed/candidate/rejected memories plus open-session artifacts; durable-vs-meta judgment is left to the model once an arc exists (lexical claim gates dropped);
- Analysis Context Compiler (
analysis_dossier) + per-source sense lenses compile the reflect/pattern brief; altitude scoring and near-duplicate condensation keep survivors at the right abstraction level; - Slack
@user/#channelhumanized at normalize time via connector metadata andexternal_identities(actor_labels) so evidence quotes stay readable; twin meditateorchestrates the full chain up to the human gates (correlate → reflect → optional review → judgment drafts); never auto-confirms Memory nor auto-approves Judgment; flags--incremental / --no-reflect / --no-propose / --review / --limit / --dry-run / --json;- daily/weekly consolidation runs cortex + reflect up to those same human gates;
pattern_reflectnight pass mines vault/project windows for durable preference/procedure/constraint candidates (still never auto-confirms); propose_from_episode/propose_from_episode_patterns(theprefrontalstage) seed pendingJudgmentProposals from confirmed trajectory memories; still preview-token + human approval;- LLM usage ledger (
twin usage) records stage/role tokens, latency and estimated cost for hot-path and analysis completions without breaking the model path; - Review resolve workbench: findings/resolve HTTP APIs and a reshaped
twin serveUI so merge, conflict, dismiss and related decisions are outcome-focused per issue; - Memories UI: altitude/status filters plus Sources / Based-in provenance accordions so people can inspect where a memory came from;
- CLI DX parity:
twin correlate/twin meditate/twin episode *show brain-stage status, deferred next-steps, tables and--json; - docs: destination README rewritten around understanding as the unit of value; framing consolidated into
IDENTITY/COGNITION/RESEARCH/GLOSSARY(OBJECTIVEremoved;FOUNDATIONSdemoted to appendix);INTERFACESsplit into hub +NATIVE/MCP/CLI/REST; ARCHITECTURE brain→CLI stage map and OPERATIONS post-backfill/twin meditateguidance updated; marketing asset set trimmed to the banner.
Follow-on (not blocking v1.3.0): multi-factor confidence composition, identity-as-graph / entity resolution, HTTP/MCP episode graph APIs, full load/replay eval suite — see Correlation depth remainder.
Goal: ship Twin as an installable public package (twin-cognition on PyPI) with a tag-driven GitHub Release pipeline, pip-first setup docs, and minimal community hygiene — without changing the import or CLI surface (import twin, twin / twin-runtime).
Delivered:
- distribution renamed to
twin-cognition(PyPI/wheel); package/__version__aligned to1.4.0; author metadata Edu Caribé; urls, keywords and classifiers for PyPI; .github/workflows/release.yml— on tagv*.*.*: build sdist/wheel, smoke-install the wheel, publish GitHub Release assets, then Trusted Publishing to TestPyPI and PyPI (environmentstestpypi/pypi);- SETUP and README install path:
pip install "twin-cognition[…]"primary; editable install under “Development from source”; - CONTRIBUTING, SECURITY, issue templates and PR template for public contribution flow;
- post-v1.3.0 product/docs polish included in this line: SETUP/OPERATIONS rewrite around the Rich
twin initwizard and end-to-end ops; README demonstration video and Similar Projects; Slack connector keeps rate-limit/network errors asdegraded(notunauthorized); ARCHITECTURE sequence diagrams for ACC, connector→pack and native sessions.
Next: ROADMAP.md · PRODUCT.md.