Skip to content

Commit 7fcc39e

Browse files
authored
FM3.2c: on-demand local Ollama interest ideas with owner review (#37)
* FM3.2c: bounded loopback local AI interests, provenance rechecks and owner-only review * Correct exact Ollama prompt JSON examples and anchored validation patterns * Launch on-demand local Friend Scout interest job after committed CSRF-checked POST * FM3.2c synthetic Ollama, owner review, source tampering, bounded worker and auth regression * Document FM3.2c local interest proposal generation, safety and acceptance * Prepare FM3.2c normal bobctl update release from FM3.2b * Assert completed local job control hides duplicate request button * Record accepted FM3.2b and handoff for bounded FM3.2c local interest proposals * Tighten loopback model allowlist to single safe Ollama name/tag, no path segments * Exercise attempt cap after clearing the second active synthetic job * Include FM3.2c local AI security tests in CI path triggers
1 parent 7bdbfd4 commit 7fcc39e

7 files changed

Lines changed: 836 additions & 10 deletions

File tree

‎.github/workflows/inventory-tests.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ on:
5151
- 'tests/test_navigation_shell.py'
5252
- 'tests/test_fm32a_interest_review.py'
5353
- 'tests/test_fm32b_watchlist.py'
54+
- 'tests/test_fm32c_local_interests.py'
5455
- 'tests/test_v071_integration.py'
5556
- 'tests/test_v071_http_smoke.py'
5657
- 'tests/test_v071_ui_update.py'
@@ -109,6 +110,7 @@ on:
109110
- 'tests/test_navigation_shell.py'
110111
- 'tests/test_fm32a_interest_review.py'
111112
- 'tests/test_fm32b_watchlist.py'
113+
- 'tests/test_fm32c_local_interests.py'
112114
- 'tests/test_v071_integration.py'
113115
- 'tests/test_v071_http_smoke.py'
114116
- 'tests/test_v071_ui_update.py'

‎docs/FRIENDS-ROADMAP-AND-HANDOFF.md‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Bob Friends Manager: FM1–FM5 Roadmap and Fresh-Chat Handoff
22

33
**Status captured:** October 29, 2026 (Pacific time; GitHub main release history includes October 30 UTC).
4-
**Current implementation phase:** **FM3.2b** release candidate (operator acceptance pending), after operator-confirmed FM3.2a. Next planned: FM3.2c evidence-bound local-model proposals.
5-
**Operator-confirmed working baseline:** `v0.7.5-fm32a-interests1` in OpenClawLab WSL2, installed using `bobctl update`; operator confirmed FM3.2a works as expected.
4+
**Current implementation phase:** **FM3.2c** owner-triggered local-model interest proposals, candidate awaiting live acceptance. FM3.2b is operator-accepted.
5+
**Operator-confirmed working baseline:** `v0.7.5-fm32b-watchlist1` in OpenClawLab WSL2, installed using `bobctl update`; operator confirmed FM3.2b works as expected.
66
**Canonical repository:** `merberg-ai/bob-openclaw-moltbook`, `main`.
77
**This file is a planning/handoff artifact only**. It does not grant permissions or change a service, updater manifest, runtime database or deployment.
88

@@ -40,13 +40,22 @@ This is the **proposed scope**, not a commitment that all four items must be shi
4040
- **Deployment:** after offline test + PR review/merge, use only `bobctl update` with standard backup and rollback. Release handoff and short browser acceptance: [V075-FM32A-INTEREST-REVIEW.md](V075-FM32A-INTEREST-REVIEW.md). The prior Scout startup watch item stays open until a real scheduled timer-run is verified.
4141
- **Security:** no publication, platform follow/DM/comment, model prompt expansion, new automatic timer, private note disclosure or change to FM1/PM2 authority.
4242

43-
### FM3.2b implementation checkpoint (operator acceptance pending)
43+
### FM3.2b operator-accepted checkpoint
4444

45-
- **Candidate:** `v0.7.5-fm32b-watchlist1` upgrading directly from operator-tested `v0.7.5-fm32a-interests1`. Two managed files: existing `bob_friend_scout.py` and generated `bob-activity-manager`; dashboard restart only.
45+
- **Operator tested:** `v0.7.5-fm32b-watchlist1` upgrading directly from operator-tested `v0.7.5-fm32a-interests1`. Two managed files: existing `bob_friend_scout.py` and generated `bob-activity-manager`; dashboard restart only.
4646
- **What changes:** ten-per-page search/filter for all active integrity-checked friends (watched, paused, integrity problems), preserving the same view after a watch toggle. Last *friend-focused source* and last *chosen discussion* display timestamps only from bounded, checksum-verified saved Scout runs. Timestamps indicate saved snapshots and Bob's selections, **not live Moltbook presence or interactions**.
4747
- **Safety:** no new background timer, untrusted private notes in requests/prompts, credentials, network access, model tools or social publication rights. Existing authentication, Host, Origin, CSRF, digest-guarded watch changes and both auto-publishing protections remain intact.
4848
- **Acceptance:** synthetic tests/CI then one operator `bobctl update` and short LAN browser checks. See [V075-FM32B-WATCHLIST.md](V075-FM32B-WATCHLIST.md). Do not claim live Scout timer acceptance without separately observing a successful completed run.
4949

50+
### FM3.2c implementation checkpoint (operator acceptance pending)
51+
52+
- **Candidate:** `v0.7.5-fm32c-localideas1`, from operator-tested `v0.7.5-fm32b-watchlist1`. Two managed files: existing `bob_friend_scout.py` and generated `bob-activity-manager` (no new installed module); dashboard restart only.
53+
- **What changes:** owner clicks an action on an existing source-verified selected discussion. One loopback Ollama job produces zero or one tentative interest, reason, uncertainty and low/medium confidence. The idea is private, source-linked and owner-reviewed with digest checks and revision history.
54+
- **Separation:** unlike FM3.2a's copied existing WHY, FM3.2c uses model synthesis from bounded *public chosen post* evidence only. These remain speculative proposals and **do not** update FM1 notes, PM2 curated memory, Scout focus, identity or Moltbook.
55+
- **Limits:** one active job, two per run, 60 proposals maximum (15 pending), fixed loopback Ollama, 90-second timeout, no automatic retrials/network browsing, sanitized failures; preserved security and publication rules. Verification repeated at job completion and review.
56+
- **Acceptance:** one `bobctl update` and short LAN browser acceptance after CI/merge, documented in [V075-FM32C-LOCAL-INTERESTS.md](V075-FM32C-LOCAL-INTERESTS.md). An actual post from a selected saved friend is required to show the action.
57+
- **Later:** an explicitly confirmed, bounded read-only single-agent public focus check remains separate. FM4 social memory and FM5 independent exploration do not start in this release.
58+
5059
## 3. FM4 — Social Memory and Evolving Relationships (NEW AGREED PHASE)
5160

5261
**Status: planned after FM3.2. Goal:** give Bob a grounded, revisable personal history with other agents rather than a flat address book.

‎docs/V075-FM32C-LOCAL-INTERESTS.md‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# FM3.2c: Bob's on-demand local interest proposals
2+
3+
**Release:** v0.7.5-fm32c-localideas1 from operator-verified v0.7.5-fm32b-watchlist1.
4+
5+
## Behavior
6+
7+
On authenticated LAN Moltbook → Friend Scout, a source-verified existing Scout selection of an active saved friend offers **Ask local Bob for a tentative interest**. This is an explicit owner action, not a scheduled task. A single daemon worker analyses only the chosen SHA-verified saved public post using loopback Ollama at 127.0.0.1:11434 and model qwen3.5:9b (model name override: BOB_FRIEND_OLLAMA_MODEL).
8+
9+
No Moltbook API requests, agent tools, or social actions occur. No private FM1 notes/interests, PM2 memories, identity files or secrets are sent into the model prompt. The model receives bounded title/content of just the verified chosen public post, with instructions that it is untrusted, inert data.
10+
11+
Output is either no idea or ONE strictly bounded, source-linked tentative interest: first-person interest (up to 180 characters), reason (180), uncertainty (140), low/medium confidence and the exact source post ID. The output is model interpretation, **not** verification of any statement, author account identity, relationship or trust.
12+
13+
The new Bob's new tentative interests inbox supports explicit approve/reject/archive/reopen. Source run/post and a SHA-sealed private record are rechecked before approval or reopening. Optimistic digest prevents stale forms, with local revision history. Approving stores only an owner decision: NO writes to FM1 operator notes, PM2 curated memory, SOUL.md, Scout preference weighting or any Moltbook publication.
14+
15+
## Guardrails
16+
17+
- Exactly one outstanding local generation job; maximum two attempts per run, 100 job rows, 60 proposal rows and 15 pending. Maximum one proposal per generation.
18+
- Fixed loopback HTTP target and path, no redirects/credentials, 90-second request timeout, maximum 32 KiB HTTP reply and 450 model output tokens. Strict structured JSON with source ID matching and unsafe instruction checks.
19+
- Saved feed integrity, chosen post UUID and author, current active friend and source snapshot hash all revalidated before prompt and after generation.
20+
- Jobs stale more than three minutes become failed/interrupted on view, with no automatic retry. Failure messages never include model output/private data.
21+
- Existing auth/Host/Origin/CSRF, six-field POST constraints, global Friend Scout OFF default, per-friend watch pause, capped Scout browsing, both friend-targeted publication guards all unchanged. Owner-triggered analysis of saved files does not itself browse online.
22+
- Two installed code files: existing bob_friend_scout.py and generated bob-activity-manager, produced from existing pinned builder. No new installed Python module, service or timer.
23+
- The normal bobctl update performs SHA checks, private DB backup, Activity Manager restart only, and guarded code rollback.
24+
25+
## Offline and live acceptance
26+
27+
Synthetic tests cover mocked Ollama, source integrity, tampering, invalid output, secrets isolation, private history/owner review, stale work, duplicate requests and exact generated-manager delta. Full CI should be green before merging.
28+
29+
After merging to main:
30+
1. Run **bobctl update** once, confirm v0.7.5-fm32b-watchlist1 → v0.7.5-fm32c-localideas1, type UPDATE.
31+
2. On Moltbook → Friend Scout, under Bob's selected friend discussions choose Ask local Bob for a tentative interest. If there are no verified saved friend choices, this control is intentionally absent. Refresh for completed status; no-interest is a legitimate result.
32+
3. Review any new proposal: its idea, reason, uncertainty, confidence and source. Approve/reject/reopen; verify private state and history changed only.
33+
4. Existing watch/pause and manual publication behavior must still work. No Moltbook follow/comment/DM can be issued by this feature.
34+
35+
## Next
36+
37+
FM3.2 optional separately confirmed, rate-limited read-only single-agent focus check remains deferred. FM4 social memory and FM5 autonomous exploration remain separate phases requiring independent design, approval and acceptance.

‎releases/current.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
22
"format": "bob-updater-v1",
3-
"release": "v0.7.5-fm32b-watchlist1",
4-
"from": "v0.7.5-fm32a-interests1",
5-
"notes": "FM3.2b ten-per-page Friend Scout filters and independent saved Scout recency. Preserve existing auth/CSRF, local watch preferences and publication guard; no network or job changes.",
3+
"release": "v0.7.5-fm32c-localideas1",
4+
"from": "v0.7.5-fm32b-watchlist1",
5+
"notes": "FM3.2c owner-triggered loopback Ollama tentative interests from SHA-verified saved friend selections; private digest-reviewed proposals, no new Scout reads or social/publication authority.",
66
"files": [
77
{
88
"name": "bob_friend_scout.py",
99
"source": "src/lib/bob/bob_friend_scout.py"
1010
},
1111
{
1212
"name": "bob-activity-manager",
13-
"builder": "scripts/build_v075_fm32b_candidate.py",
13+
"builder": "scripts/build_v075_fm32c_candidate.py",
1414
"index": 0
1515
}
1616
],
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python3
2+
"""FM3.2c: authenticated local-only Friend Scout AI job launcher.
3+
4+
Patch ONLY the verified FM3.2b manager builder output. Existing Basic auth,
5+
Origin, Host, CSRF and six-field form limits run before generation can start.
6+
Worker starts after queued DB transaction commits; dashboard remains responsive.
7+
"""
8+
from __future__ import annotations
9+
import build_v075_fm32b_candidate as prior
10+
11+
12+
def once(text,old,new):
13+
if text.count(old)!=1:
14+
raise ValueError("FM3.2c manager baseline drift; refusing release build")
15+
return text.replace(old,new,1)
16+
17+
18+
def build():
19+
manager,nav=prior.build()
20+
code=manager.decode("utf-8")
21+
code=once(code,
22+
"watchlist_location as friend_scout_return_path)",
23+
"watchlist_location as friend_scout_return_path, "
24+
"interest_ai_worker as friend_interest_ai_worker)")
25+
code=once(code,
26+
" friend_scout_change(db,form)\n"
27+
" self.send_response(303)",
28+
" outcome=friend_scout_change(db,form)\n"
29+
" if isinstance(outcome,str) and outcome.startswith('ai-job:'):\n"
30+
" threading.Thread(target=friend_interest_ai_worker,\n"
31+
" args=(outcome[7:],publish_conn),daemon=True,\n"
32+
" name='bob-friend-interest-ai').start()\n"
33+
" self.send_response(303)")
34+
compile(code,"bob-activity-manager","exec")
35+
return code.encode("utf-8"),nav
36+
37+
38+
if __name__=="__main__":
39+
manager,nav=build()
40+
print("FM3.2c LOCAL INTEREST AI CANDIDATE: PASS")
41+
print("manager_bytes:",len(manager),"navigation_bytes:",len(nav))
42+
print("production_modified: NO")

0 commit comments

Comments
 (0)