Skip to content

docs(adr): 0024 — present-tense self-model, reasoned routing, measured reply loop - #231

Merged
dshakes merged 2 commits into
masterfrom
docs/adr-0024-present-tense-self-model
Sep 4, 2026
Merged

dshakes merged 2 commits into
masterfrom
docs/adr-0024-present-tense-self-model

Conversation

@dshakes

@dshakes dshakes commented Sep 4, 2026

Copy link
Copy Markdown
Owner

The plan behind #224–#230, written down so it outlives the session.

Context is fourteen root-caused production failures (2026-08-23 → 09-04), each with its actual cause and PR. Three things about that list drive the plan:

  • None of the fourteen threw an error. Every one was a silent drop, a stale flag, a missing log line, or a fact the prompt could not represent.
  • The owner told the assistant the facts and they never reached the bot. "We're opening Sep 10" was said on 08-23; twelve days later the bridge had no representation of it.
  • Static classifiers pre-empt reasoning at every gate a contact can see — wordlists, regexes, a hash-indexed greeting table.

Decision is five workstreams in dependency order, each with its invariant, gate, and files:

Workstream
W1 Present-tense self-model (## Now), teaching from every channel, contact path reads working memory, reasoned relationship inference
W2 Reasoned gates replace string tables where a wrong call reaches a contact (greeting fallback, claim rewriter, topic key, register, language confirm)
W3 Guard coverage derived from the audited failures: repeat-skeleton, the "want me to…" tic, promise ledger, critique against the owner's own text
W4 Every reply measured; "sounds like me" gets an authorship score with a human floor — no LLM judge (shown circular)
W5 Silence is a bug; a merge is not a deploy — make deploy-local proves the restart

Explicitly not doing: more exemplars, fine-tuning, multi-agent fan-out on the reply path — all measured null or negative in the 2026 literature. No new store; the pgvector index already exists.

Sequencing puts the deploy step first, because six PRs were "merged" while three services ran code from July and August.

…sured reply loop

The plan behind PRs #224–#230, written down so it outlives the session that
produced it. Fourteen root-caused production failures from 2026-08-23 to
2026-09-04 are the Context; five workstreams derived from them are the
Decision.

The three findings the plan rests on:
  - none of the fourteen threw an error — every one was silent
  - the owner told the assistant the facts and they never reached the bot
  - static classifiers pre-empt the model at every gate a contact can see

And the three things the 2026 literature says NOT to do, so nobody relitigates
them: no more exemplars, no fine-tuning, no multi-agent fan-out on the reply
path. Sequenced so the deploy step comes first (three services ran stale code
for weeks) and the measurement loop comes before any voice change it would
have to judge.
@compass-sdlc-bot compass-sdlc-bot Bot added the agent:reviewed-clean Reviewer found no Blocking issues this round label Sep 4, 2026
@github-actions github-actions Bot added the domain:docs Docs-only change label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🔷 Gemini cross-audit (agent:audit-gemini)

Here is the independent audit of ADR 0024 (pr-diff.patch).


🚨 BLOCKING: Security & Privacy Vulnerabilities

1. Outbound Fact Leakage via Automated Cross-Channel Extraction (W1.2 & W1.1)

  • The Issue: Auto-extracting "facts" from any message the owner sends to anyone (W1.2) is a massive privacy risk. Sarcastic, temporary, or intimate comments sent to a trusted friend could be extracted as biographical ground truth. Because the newly proposed ## Now section is injected into prompts for both the owner and arbitrary contacts, these private elements will inevitably leak to third parties.
  • Remedy: Do not auto-extract facts from outgoing third-party messages. Restrict automated profile updates strictly to the dedicated owner-only self-chat channel and explicit lantern teach CLI actions.

2. Cross-Contact Data Leakage under Attribution Failures (W1.3)

  • The Issue: Attributing working memory actions to specific contacts (WorkingAction.contact) and reading them on the contact path creates a leak vector. If there is a bug in JID/handle normalization or contact matching (similar to Row 6 where a cached null mapped ten contacts to the owner), actions and events belonging to one contact will be exposed to another.
  • Remedy: JIDs/handles must be strictly normalized and validated. Implement a hard fail-closed check: if the contact attribution is unresolved or has any ambiguity, do not output the action block.

🚨 BLOCKING: Performance & Latency Explosion

1. Serial LLM Chaining on the Outbound Reply Hot-Path (W2, W3)

  • The Issue: The proposed pipeline chains up to 5 sequential LLM/Database hops per reply:
    1. Initial Draft Generation.
    2. Language Confirmation (if scorer < 0.7).
    3. PerFine (Critique-Refine) against 5 DB-retrieved owner messages.
    4. Bot-Tell & Repeat-Skeleton Evaluation.
    5. Promise Ledger verification & Rewrite.
  • Impact: This sequential chain will easily drive response latencies past 30–60 seconds and inflate token costs by orders of magnitude. Extreme lag in an instant messaging thread screams "bot" far louder than style anomalies.
  • Remedy: Consolidate. Merge the tone, language, and promise detection into the initial system prompt or a single joint post-generation pass rather than serializing multiple individual LLM hops.

⚠️ Correctness, Edge Cases, & Fragility

1. Infinite Loops in repeat-skeleton Detection (W3.1)

  • The Issue: Suppressing drafts that match a prior reply's structural skeleton can trigger infinite regeneration loops on common short responses (e.g., "Yeah", "Sounds good", "Thanks!").
  • Remedy: Enforce a strict limit on regeneration attempts (max 2), falling back to the deterministic safety-net or a silent drop if the threshold is exceeded.

2. Race Conditions in Claim Verification (W2.2)

  • The Issue: Checking recentActions to decide whether to rewrite a claim (e.g., "I added that to your calendar") is prone to race conditions if the actual action runs asynchronously or experiences database write lag. The check may execute before the action's success is written, causing the bot to falsely rewrite the sentence to "I will add..." and sound contradictory.
  • Remedy: Ensure action execution is strictly synchronous or uses a distributed lock state before generating the reply.

3. Fragile Static Analysis for Liveness (W5.1)

  • The Issue: The liveness test enforcing that every early return have a logger.* statement within 6 lines is too fragile. It will trigger false build failures on inline utility maps, error handling bubble-ups, and nested callback helper functions.
  • Remedy: Use structured AST linting rules (via ESLint) rather than regex-based line offsets to enforce logging boundaries on high-level route handlers.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🔎 Codex cross-audit (agent:audit)

Blocking

  1. docs/adr/0024-present-tense-self-model.md commits real personal/business context into the repo: owner facts, dates, names, contact/thread details, and production chat metadata. This conflicts with the existing owner-profile privacy model that says real profile data lives outside the repo and ordinary profile lines can shape third-party replies. See owner-profile.example.md and owner-profile.ts. This ADR should be scrubbed to anonymized incidents before merge.

  2. docs/adr/0024-present-tense-self-model.md proposes auto-teaching from the owner’s sent messages to anyone into owner-profile.md. That violates the current security invariant that the profile is deliberately owner-curated because it is injected into contact-facing replies. It also bypasses the existing confirmation guard for authoritative typed facts, which explicitly treats wrong auto-written facts as critical. See owner-profile-auto-update.ts. The design needs an explicit consent/confirmation path and audience classification before this is accepted.

Non-blocking

  • docs/adr/0024-present-tense-self-model.md creates a new persistent reply corpus containing inbound and outbound message text, but line 239 says “No new store.” That understates the privacy surface. The ADR should call this a new PII corpus and specify retention, encryption key location, deletion, and exclusion from repo paths/backups.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🛡️ Vuln scan — ❌ vulnerable dependency found

cd services/control-plane && govulncheck ./...
=== Symbol Results ===

No vulnerabilities found.

Your code is affected by 0 vulnerabilities.
This scan also found 1 vulnerability in packages you import and 18
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
Use '-show verbose' for more details.
cd services/gateway && cargo audit
    Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
      Loaded 1239 security advisories (from /home/runner/.cargo/advisory-db)
    Updating crates.io index
    Scanning Cargo.lock for vulnerabilities (272 crate dependencies)
cd services/model-router && cargo audit
    Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
      Loaded 1239 security advisories (from /home/runner/.cargo/advisory-db)
    Updating crates.io index
    Scanning Cargo.lock for vulnerabilities (251 crate dependencies)
cd services/runtime-manager && cargo audit
    Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
      Loaded 1239 security advisories (from /home/runner/.cargo/advisory-db)
    Updating crates.io index
    Scanning Cargo.lock for vulnerabilities (480 crate dependencies)
Crate:     wasmtime
Version:   46.0.2
Title:     Guest controlled-size host heap allocation through WASIp3 streams
Date:      2026-08-20
ID:        RUSTSEC-2026-0268
URL:       https://rustsec.org/advisories/RUSTSEC-2026-0268
Severity:  6.9 (medium)
Solution:  Upgrade to >=46.0.3, <47.0.0 OR >=47.0.4

Crate:     wasmtime
Version:   46.0.2
Title:     Filesystem sandbox escape when paths or symlinks contain trailing slashes
Date:      2026-08-20
ID:        RUSTSEC-2026-0269
URL:       https://rustsec.org/advisories/RUSTSEC-2026-0269
Severity:  8.8 (high)
Solution:  Upgrade to >=24.0.13, <25.0.0 OR >=36.0.14, <37.0.0 OR >=46.0.3, <47.0.0 OR >=47.0.4

Crate:     chacha20
Version:   0.10.0
Warning:   yanked

error: 2 vulnerabilities found!
warning: 1 allowed warning found
make: *** [Makefile:270: audit] Error 1

@dshakes
dshakes merged commit 2501394 into master Sep 4, 2026
8 checks passed
@dshakes
dshakes deleted the docs/adr-0024-present-tense-self-model branch September 4, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:reviewed-clean Reviewer found no Blocking issues this round domain:docs Docs-only change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant