From fa2cdc9a5c9da0289d84ab3ea355d489448dc8a2 Mon Sep 17 00:00:00 2001 From: Sami Rusani Date: Thu, 9 Apr 2026 01:28:58 +0200 Subject: [PATCH] docs: refresh README and scrub personal path identifiers --- README.md | 308 +++++++++++++++--- REVIEW_REPORT.md | 12 +- .../src/alicebot_api/retrieval_evaluation.py | 11 +- .../phase9-sprint-33-control-tower-packet.md | 54 +-- eval/baselines/phase9_s37_baseline.json | 18 +- eval/reports/phase9_eval_latest.json | 18 +- tests/integration/test_context_compile.py | 2 +- tests/integration/test_entities_api.py | 2 +- tests/integration/test_entity_edges_api.py | 2 +- tests/unit/test_compiler.py | 6 +- tests/unit/test_entity.py | 6 +- tests/unit/test_main.py | 6 +- tests/unit/test_phase9_eval.py | 17 +- 13 files changed, 358 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index e8d5d01..077fa8e 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,293 @@ + + # Alice -Alice is a local-first memory and continuity engine for AI agents. +**The memory and continuity layer for AI agents.** + +![Local-first](https://img.shields.io/badge/local--first-core-0A7B61) +![MCP](https://img.shields.io/badge/MCP-supported-1f6feb) +![License](https://img.shields.io/badge/license-MIT-2ea043) + +Alice gives agents something most assistants still lack: +**durable memory, clean resumption, open-loop continuity, and correction-aware context.** + +Instead of forcing you to restate context over and over, Alice helps your tools and agents remember what matters, resume work intelligently, and improve when corrected. + +## What Alice does + +Alice helps agents and users: + +- **Capture** important notes, decisions, and commitments quickly +- **Recall** what was decided about a person, project, or topic +- **Resume** work without rereading long threads +- **Track open loops** like waiting-fors, blockers, and stale items +- **Correct memory** so future answers improve deterministically + +## Why Alice exists + +Most AI assistants still break in the same places: + +- they forget why decisions were made +- they lose context between sessions +- they treat memory as vague summaries +- they make correction hard +- they do not help you resume interrupted work + +Alice is built to solve that. + +It is a **local-first continuity engine** with: + +- structured memory revisions +- deterministic recall and resumption +- provenance-aware corrections +- open-loop management +- MCP access for external agents +- importers for existing workflows + +## Who it is for + +Alice is built for: + +- founders +- operators +- consultants +- researchers +- technical teams +- agent builders +- anyone who wants their AI systems to remember and resume work properly + +## What makes Alice different + +### Memory that can be corrected + +Alice does not just store chats. +It keeps explicit continuity objects and supports review, correction, and supersession. + +### Resumption, not just search + +Alice is designed to answer: + +- What did we decide? +- What changed? +- What am I waiting on? +- Get me back into this project. + +### Agent-agnostic by design -Phase 9 is complete. Alice Connect is the planned Phase 10 product layer on top of that shipped core, `P10-S1` through `P10-S4` are shipped, and `P10-S5` is the active execution sprint. +Use Alice on its own, through the CLI, through MCP, or alongside external agent systems. -## What v0.1 Ships +### Local-first core -- local-first runtime (`docker compose`, Postgres, API) -- continuity CLI (`python -m alicebot_api` / `alicebot`) -- MCP server (`python -m alicebot_api.mcp_server` / `alicebot-mcp`) -- shipped importer paths: OpenClaw, Markdown, ChatGPT export -- reproducible evaluation harness (`./scripts/run_phase9_eval.sh`) +Alice Core runs locally and keeps continuity close to the user. + +## Current surfaces + +Today, Alice ships with: + +- **Alice Core** +- **CLI** +- **MCP server** +- **OpenClaw adapter** +- **Importers** + - OpenClaw + - Markdown + - ChatGPT exports ## Quickstart -Run this path on a clean checkout: +> Replace these commands with your exact final install path before launch. ```bash +git clone https://github.com/your-org/alice.git +cd alice cp .env.example .env -python3 -m venv .venv -./.venv/bin/python -m pip install -e '.[dev]' docker compose up -d -./scripts/migrate.sh -./scripts/load_sample_data.sh -APP_RELOAD=false ./scripts/api_dev.sh ``` -In another terminal: +Check status: + +```bash +alice status +``` + +Capture something: + +```bash +alice capture "Remember that the Q3 board pack is due on Thursday." +``` + +Recall it later: ```bash -curl -sS http://127.0.0.1:8000/healthz -./.venv/bin/python -m alicebot_api status -./.venv/bin/python -m alicebot_api recall --query local-first --limit 5 -./.venv/bin/python -m alicebot_api resume --max-recent-changes 5 --max-open-loops 5 +alice recall "What do I know about the Q3 board pack?" ``` -Detailed guide: [docs/quickstart/local-setup-and-first-result.md](docs/quickstart/local-setup-and-first-result.md) +Resume work: + +```bash +alice resume q3-board-pack +``` + +Review open loops: + +```bash +alice open-loops +``` + +Correct memory: + +```bash +alice correct-memory +``` + +## Use Alice with your agents + +Alice is designed to be a continuity layer, not a closed assistant silo. + +### MCP + +Alice exposes a narrow, stable MCP surface for continuity workflows: + +- `alice_capture` +- `alice_recall` +- `alice_resume` +- `alice_open_loops` +- `alice_recent_decisions` +- `alice_recent_changes` +- `alice_memory_review` +- `alice_memory_correct` +- `alice_context_pack` + +This makes it easy to connect Alice to MCP-capable assistants and development environments. + +See: + +- [docs/integrations/mcp.md](docs/integrations/mcp.md) + +### OpenClaw + +Alice includes an OpenClaw integration path for import and augmentation. + +You can: + +- import existing OpenClaw memory into Alice +- normalize it into Alice continuity objects +- use Alice recall and resumption on imported work +- augment OpenClaw workflows through Alice MCP tools + +See: + +- [docs/integrations/importers.md](docs/integrations/importers.md) + +## Example workflows + +### Founder continuity + +- capture strategic decisions +- resume fundraising or product threads +- track waiting-fors and follow-ups +- stop losing context across days and weeks + +### Consulting continuity + +- recall client decisions +- resume project threads fast +- maintain open loops without building a manual CRM ritual + +### Agent memory upgrade + +- plug Alice into your existing agent stack +- improve recall, resumption, and correction +- avoid rebuilding your whole runtime + +## Architecture at a glance + +Alice is built around a shared continuity core: + +- immutable events +- structured memory revisions +- provenance-aware recall +- deterministic resumption briefs +- open-loop objects +- MCP and CLI surfaces on the same semantics + +This means Alice behaves consistently whether you use: + +- CLI +- MCP +- imported data +- external adapters + +## Why people share Alice + +Because Alice solves a very real problem: +your AI can only be useful if it can remember, resume, and stay aligned with how you actually work. + +## Roadmap + +### Available now + +- local-first core +- CLI +- MCP +- importers +- OpenClaw adapter +- reproducible eval harness + +### In progress + +- Alice Connect +- hosted identity and workspace bootstrap +- Telegram-first conversational surface +- chat-native approvals +- daily continuity briefs + +## Docs + +- [Quickstart](docs/quickstart/local-setup-and-first-result.md) +- [Architecture](ARCHITECTURE.md) +- [MCP](docs/integrations/mcp.md) +- [Integrations](docs/integrations/importers.md) +- [Examples](docs/examples/phase9-command-walkthrough.md) + +## Tags + +`ai-memory` `agent-memory` `durable-memory` `continuity-layer` `mcp` `local-first` `resumption` `open-loops` `ai-agents` `memory-correction` + +## GitHub Topics To Set + +Use these in GitHub repository settings (`About` -> `Edit` -> `Topics`): + +- [ ] `ai-memory` +- [ ] `agent-memory` +- [ ] `mcp` +- [ ] `local-first` +- [ ] `continuity-layer` +- [ ] `durable-memory` +- [ ] `context-engineering` +- [ ] `developer-tools` +- [ ] `openclaw` +- [ ] `memory-correction` + +## Contributing + +We welcome issues, adapters, importers, eval contributions, and integration examples. + +See: + +- [CONTRIBUTING.md](CONTRIBUTING.md) -## Integration Docs +## Security -- CLI: [docs/integrations/cli.md](docs/integrations/cli.md) -- MCP: [docs/integrations/mcp.md](docs/integrations/mcp.md) -- Importers: [docs/integrations/importers.md](docs/integrations/importers.md) -- Walkthrough: [docs/examples/phase9-command-walkthrough.md](docs/examples/phase9-command-walkthrough.md) +If you discover a security issue, please report it through the process in: -## Evaluation And Release +- [SECURITY.md](SECURITY.md) -- Eval harness: `./scripts/run_phase9_eval.sh` -- Baseline: `eval/baselines/phase9_s37_baseline.json` -- Latest report path: `eval/reports/phase9_eval_latest.json` -- Release checklist: [docs/release/v0.1.0-release-checklist.md](docs/release/v0.1.0-release-checklist.md) -- Release tag plan: [docs/release/v0.1.0-tag-plan.md](docs/release/v0.1.0-tag-plan.md) -- Release runbook: [docs/runbooks/phase9-public-release-runbook.md](docs/runbooks/phase9-public-release-runbook.md) +## License -## Canonical Docs +See: -- Product: [PRODUCT_BRIEF.md](PRODUCT_BRIEF.md) -- Architecture: [ARCHITECTURE.md](ARCHITECTURE.md) -- Roadmap: [ROADMAP.md](ROADMAP.md) -- Rules: [RULES.md](RULES.md) -- Current state: [.ai/handoff/CURRENT_STATE.md](.ai/handoff/CURRENT_STATE.md) -- Historical planning and control docs: [docs/archive/planning/2026-04-08-context-compaction/README.md](docs/archive/planning/2026-04-08-context-compaction/README.md) +- [LICENSE](LICENSE) diff --git a/REVIEW_REPORT.md b/REVIEW_REPORT.md index 4bd6a0f..0219e8e 100644 --- a/REVIEW_REPORT.md +++ b/REVIEW_REPORT.md @@ -4,7 +4,7 @@ PASS ## criteria met -- Hosted admin/support visibility for `P10-S5` is implemented with all in-scope endpoints in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py): +- Hosted admin/support visibility for `P10-S5` is implemented with all in-scope endpoints in [`apps/api/src/alicebot_api/main.py`](apps/api/src/alicebot_api/main.py): - `GET /v1/admin/hosted/overview` - `GET /v1/admin/hosted/workspaces` - `GET /v1/admin/hosted/delivery-receipts` @@ -13,14 +13,14 @@ PASS - `PATCH /v1/admin/hosted/rollout-flags` - `GET /v1/admin/hosted/analytics` - `GET /v1/admin/hosted/rate-limits` -- In-scope data additions are present in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/alembic/versions/20260409_0047_phase10_beta_hardening_launch.py`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/alembic/versions/20260409_0047_phase10_beta_hardening_launch.py), including `chat_telemetry` plus additive rollout/support/rate-limit/incident evidence fields. +- In-scope data additions are present in [`apps/api/alembic/versions/20260409_0047_phase10_beta_hardening_launch.py`](apps/api/alembic/versions/20260409_0047_phase10_beta_hardening_launch.py), including `chat_telemetry` plus additive rollout/support/rate-limit/incident evidence fields. - Hosted chat and scheduled-delivery paths enforce deterministic rollout and abuse/rate-limit controls with telemetry evidence. - Onboarding failure-state visibility is hardened and now avoids cross-tenant side effects: - - admin access requires explicit operator authorization (`hosted_admin_read` + `hosted_admin_operator`) in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:1557`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:1557). - - bootstrap failure recording only occurs after a resolved member workspace (`resolved_workspace_id` no longer trusts request input) in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:5069`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:5069). + - admin access requires explicit operator authorization (`hosted_admin_read` + `hosted_admin_operator`) in [`apps/api/src/alicebot_api/main.py:1557`](apps/api/src/alicebot_api/main.py:1557). + - bootstrap failure recording only occurs after a resolved member workspace (`resolved_workspace_id` no longer trusts request input) in [`apps/api/src/alicebot_api/main.py:5069`](apps/api/src/alicebot_api/main.py:5069). - Rollout patch scope is constrained to hosted flags and caller cohort: - - hosted-only key guard in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/hosted_rollout.py:55`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/hosted_rollout.py:55). - - caller-cohort enforcement in [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/hosted_rollout.py:221`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/hosted_rollout.py:221) and [`/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:5568`](/Users/samirusani/Desktop/Codex/AliceBot/apps/api/src/alicebot_api/main.py:5568). + - hosted-only key guard in [`apps/api/src/alicebot_api/hosted_rollout.py:55`](apps/api/src/alicebot_api/hosted_rollout.py:55). + - caller-cohort enforcement in [`apps/api/src/alicebot_api/hosted_rollout.py:221`](apps/api/src/alicebot_api/hosted_rollout.py:221) and [`apps/api/src/alicebot_api/main.py:5568`](apps/api/src/alicebot_api/main.py:5568). - Launch-facing OSS-vs-hosted clarity updates are present in sprint-owned web/docs surfaces (`README`, admin/onboarding/home shell copy). - `P10-S1` through `P10-S4` behavior remains baseline truth; `P10-S5` changes are additive hardening/control-plane seams. - Control docs are aligned to an active `P10-S5` execution sprint and baseline-shipped `P10-S1` through `P10-S4` state: diff --git a/apps/api/src/alicebot_api/retrieval_evaluation.py b/apps/api/src/alicebot_api/retrieval_evaluation.py index c3ea514..af01143 100644 --- a/apps/api/src/alicebot_api/retrieval_evaluation.py +++ b/apps/api/src/alicebot_api/retrieval_evaluation.py @@ -303,6 +303,15 @@ def _repo_root() -> Path: return Path(__file__).resolve().parents[4] +def _public_source_path(source_path: Path) -> str: + resolved = source_path.expanduser().resolve() + repo_root = _repo_root() + try: + return resolved.relative_to(repo_root).as_posix() + except ValueError: + return f"external/{resolved.name}" + + def _as_int(value: object) -> int: if isinstance(value, bool): return int(value) @@ -411,7 +420,7 @@ def _run_phase9_importer_evidence( { "importer": definition.importer_name, "source_kind": definition.source_kind, - "source_path": str(definition.source_path.expanduser().resolve()), + "source_path": _public_source_path(definition.source_path), "first_run": first_run, "second_run": second_run, "import_success": import_success, diff --git a/docs/archive/planning/2026-04-08-context-compaction/phase9-sprint-33-control-tower-packet.md b/docs/archive/planning/2026-04-08-context-compaction/phase9-sprint-33-control-tower-packet.md index 0f9ffa1..872bf33 100644 --- a/docs/archive/planning/2026-04-08-context-compaction/phase9-sprint-33-control-tower-packet.md +++ b/docs/archive/planning/2026-04-08-context-compaction/phase9-sprint-33-control-tower-packet.md @@ -16,15 +16,15 @@ Package the existing internal Alice substrate so an external technical user can ## Required Planning Inputs -- [PRODUCT_BRIEF.md](/Users/samirusani/Desktop/Codex/AliceBot/PRODUCT_BRIEF.md) -- [ARCHITECTURE.md](/Users/samirusani/Desktop/Codex/AliceBot/ARCHITECTURE.md) -- [ROADMAP.md](/Users/samirusani/Desktop/Codex/AliceBot/ROADMAP.md) -- [RULES.md](/Users/samirusani/Desktop/Codex/AliceBot/RULES.md) -- [.ai/handoff/CURRENT_STATE.md](/Users/samirusani/Desktop/Codex/AliceBot/.ai/handoff/CURRENT_STATE.md) -- [.ai/active/SPRINT_PACKET.md](/Users/samirusani/Desktop/Codex/AliceBot/.ai/active/SPRINT_PACKET.md) -- [phase9-product-spec.md](/Users/samirusani/Desktop/Codex/AliceBot/docs/archive/planning/2026-04-08-context-compaction/phase9-product-spec.md) -- [phase9-sprint-33-38-plan.md](/Users/samirusani/Desktop/Codex/AliceBot/docs/archive/planning/2026-04-08-context-compaction/phase9-sprint-33-38-plan.md) -- [phase9-public-core-boundary.md](/Users/samirusani/Desktop/Codex/AliceBot/docs/phase9-public-core-boundary.md) +- [PRODUCT_BRIEF.md](../../../../PRODUCT_BRIEF.md) +- [ARCHITECTURE.md](../../../../ARCHITECTURE.md) +- [ROADMAP.md](../../../../ROADMAP.md) +- [RULES.md](../../../../RULES.md) +- [.ai/handoff/CURRENT_STATE.md](../../../../.ai/handoff/CURRENT_STATE.md) +- [.ai/active/SPRINT_PACKET.md](../../../../.ai/active/SPRINT_PACKET.md) +- [phase9-product-spec.md](phase9-product-spec.md) +- [phase9-sprint-33-38-plan.md](phase9-sprint-33-38-plan.md) +- [phase9-public-core-boundary.md](../../../phase9-public-core-boundary.md) ## Scope @@ -57,13 +57,13 @@ Primary outcome: - public-facing package boundary is explicit enough that later CLI and MCP work can target stable seams Likely files: -- [ARCHITECTURE.md](/Users/samirusani/Desktop/Codex/AliceBot/ARCHITECTURE.md) -- [PRODUCT_BRIEF.md](/Users/samirusani/Desktop/Codex/AliceBot/PRODUCT_BRIEF.md) -- [README.md](/Users/samirusani/Desktop/Codex/AliceBot/README.md) -- [pyproject.toml](/Users/samirusani/Desktop/Codex/AliceBot/pyproject.toml) -- [docker-compose.yml](/Users/samirusani/Desktop/Codex/AliceBot/docker-compose.yml) -- [LICENSE](/Users/samirusani/Desktop/Codex/AliceBot/LICENSE) -- [docs/phase9-public-core-boundary.md](/Users/samirusani/Desktop/Codex/AliceBot/docs/phase9-public-core-boundary.md) +- [ARCHITECTURE.md](../../../../ARCHITECTURE.md) +- [PRODUCT_BRIEF.md](../../../../PRODUCT_BRIEF.md) +- [README.md](../../../../README.md) +- [pyproject.toml](../../../../pyproject.toml) +- [docker-compose.yml](../../../../docker-compose.yml) +- [LICENSE](../../../../LICENSE) +- [docs/phase9-public-core-boundary.md](../../../phase9-public-core-boundary.md) Tasks: - define what is in `alice-core` versus still internal @@ -85,10 +85,10 @@ Primary outcome: - external user can stand up the system from scratch and load usable sample data Likely files: -- [.env.example](/Users/samirusani/Desktop/Codex/AliceBot/.env.example) -- [scripts/migrate.sh](/Users/samirusani/Desktop/Codex/AliceBot/scripts/migrate.sh) -- [scripts/api_dev.sh](/Users/samirusani/Desktop/Codex/AliceBot/scripts/api_dev.sh) -- [scripts/dev_up.sh](/Users/samirusani/Desktop/Codex/AliceBot/scripts/dev_up.sh) +- [.env.example](../../../../.env.example) +- [scripts/migrate.sh](../../../../scripts/migrate.sh) +- [scripts/api_dev.sh](../../../../scripts/api_dev.sh) +- [scripts/dev_up.sh](../../../../scripts/dev_up.sh) - `fixtures/` or equivalent sample-data location - relevant API bootstrap/seed helpers under `apps/api` or `scripts` @@ -112,9 +112,9 @@ Primary outcome: - repo onboarding works for an external technical user without prior Alice context Likely files: -- [README.md](/Users/samirusani/Desktop/Codex/AliceBot/README.md) -- [ROADMAP.md](/Users/samirusani/Desktop/Codex/AliceBot/ROADMAP.md) -- [.ai/handoff/CURRENT_STATE.md](/Users/samirusani/Desktop/Codex/AliceBot/.ai/handoff/CURRENT_STATE.md) +- [README.md](../../../../README.md) +- [ROADMAP.md](../../../../ROADMAP.md) +- [.ai/handoff/CURRENT_STATE.md](../../../../.ai/handoff/CURRENT_STATE.md) - new quickstart docs if introduced under `docs/quickstart/` Tasks: @@ -178,10 +178,10 @@ If a dedicated sample-data or smoke command is added this sprint, include it in ## Docs To Update -- [README.md](/Users/samirusani/Desktop/Codex/AliceBot/README.md) -- [ARCHITECTURE.md](/Users/samirusani/Desktop/Codex/AliceBot/ARCHITECTURE.md) -- [ROADMAP.md](/Users/samirusani/Desktop/Codex/AliceBot/ROADMAP.md) -- [.ai/handoff/CURRENT_STATE.md](/Users/samirusani/Desktop/Codex/AliceBot/.ai/handoff/CURRENT_STATE.md) +- [README.md](../../../../README.md) +- [ARCHITECTURE.md](../../../../ARCHITECTURE.md) +- [ROADMAP.md](../../../../ROADMAP.md) +- [.ai/handoff/CURRENT_STATE.md](../../../../.ai/handoff/CURRENT_STATE.md) - any new quickstart or packaging docs introduced in-sprint - ADRs for blocking packaging decisions diff --git a/eval/baselines/phase9_s37_baseline.json b/eval/baselines/phase9_s37_baseline.json index 428872b..7ff6cab 100644 --- a/eval/baselines/phase9_s37_baseline.json +++ b/eval/baselines/phase9_s37_baseline.json @@ -28,7 +28,7 @@ ], "provenance_source_kind": "openclaw_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json", + "source_path": "fixtures/openclaw/workspace_v1.json", "status": "ok", "total_candidates": 5, "workspace_id": "openclaw-workspace-demo-001", @@ -44,14 +44,14 @@ "imported_object_ids": [], "provenance_source_kind": "openclaw_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json", + "source_path": "fixtures/openclaw/workspace_v1.json", "status": "noop", "total_candidates": 5, "workspace_id": "openclaw-workspace-demo-001", "workspace_name": "OpenClaw Interop Demo" }, "source_kind": "openclaw_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json" + "source_path": "fixtures/openclaw/workspace_v1.json" }, { "duplicate_posture_ok": true, @@ -73,7 +73,7 @@ ], "provenance_source_kind": "markdown_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md", + "source_path": "fixtures/importers/markdown/workspace_v1.md", "status": "ok", "total_candidates": 5, "workspace_id": "markdown-workspace-demo-001", @@ -89,14 +89,14 @@ "imported_object_ids": [], "provenance_source_kind": "markdown_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md", + "source_path": "fixtures/importers/markdown/workspace_v1.md", "status": "noop", "total_candidates": 5, "workspace_id": "markdown-workspace-demo-001", "workspace_name": "Markdown Import Demo" }, "source_kind": "markdown_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md" + "source_path": "fixtures/importers/markdown/workspace_v1.md" }, { "duplicate_posture_ok": true, @@ -118,7 +118,7 @@ ], "provenance_source_kind": "chatgpt_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json", + "source_path": "fixtures/importers/chatgpt/workspace_v1.json", "status": "ok", "total_candidates": 5, "workspace_id": "chatgpt-workspace-demo-001", @@ -134,14 +134,14 @@ "imported_object_ids": [], "provenance_source_kind": "chatgpt_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json", + "source_path": "fixtures/importers/chatgpt/workspace_v1.json", "status": "noop", "total_candidates": 5, "workspace_id": "chatgpt-workspace-demo-001", "workspace_name": "ChatGPT Import Demo" }, "source_kind": "chatgpt_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json" + "source_path": "fixtures/importers/chatgpt/workspace_v1.json" } ], "recall_precision_checks": [ diff --git a/eval/reports/phase9_eval_latest.json b/eval/reports/phase9_eval_latest.json index acfd76c..d93e90f 100644 --- a/eval/reports/phase9_eval_latest.json +++ b/eval/reports/phase9_eval_latest.json @@ -28,7 +28,7 @@ ], "provenance_source_kind": "openclaw_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json", + "source_path": "fixtures/openclaw/workspace_v1.json", "status": "ok", "total_candidates": 5, "workspace_id": "openclaw-workspace-demo-001", @@ -44,14 +44,14 @@ "imported_object_ids": [], "provenance_source_kind": "openclaw_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json", + "source_path": "fixtures/openclaw/workspace_v1.json", "status": "noop", "total_candidates": 5, "workspace_id": "openclaw-workspace-demo-001", "workspace_name": "OpenClaw Interop Demo" }, "source_kind": "openclaw_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/openclaw/workspace_v1.json" + "source_path": "fixtures/openclaw/workspace_v1.json" }, { "duplicate_posture_ok": true, @@ -73,7 +73,7 @@ ], "provenance_source_kind": "markdown_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md", + "source_path": "fixtures/importers/markdown/workspace_v1.md", "status": "ok", "total_candidates": 5, "workspace_id": "markdown-workspace-demo-001", @@ -89,14 +89,14 @@ "imported_object_ids": [], "provenance_source_kind": "markdown_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md", + "source_path": "fixtures/importers/markdown/workspace_v1.md", "status": "noop", "total_candidates": 5, "workspace_id": "markdown-workspace-demo-001", "workspace_name": "Markdown Import Demo" }, "source_kind": "markdown_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/markdown/workspace_v1.md" + "source_path": "fixtures/importers/markdown/workspace_v1.md" }, { "duplicate_posture_ok": true, @@ -118,7 +118,7 @@ ], "provenance_source_kind": "chatgpt_import", "skipped_duplicates": 1, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json", + "source_path": "fixtures/importers/chatgpt/workspace_v1.json", "status": "ok", "total_candidates": 5, "workspace_id": "chatgpt-workspace-demo-001", @@ -134,14 +134,14 @@ "imported_object_ids": [], "provenance_source_kind": "chatgpt_import", "skipped_duplicates": 5, - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json", + "source_path": "fixtures/importers/chatgpt/workspace_v1.json", "status": "noop", "total_candidates": 5, "workspace_id": "chatgpt-workspace-demo-001", "workspace_name": "ChatGPT Import Demo" }, "source_kind": "chatgpt_import", - "source_path": "/Users/samirusani/Desktop/Codex/AliceBot/fixtures/importers/chatgpt/workspace_v1.json" + "source_path": "fixtures/importers/chatgpt/workspace_v1.json" } ], "recall_precision_checks": [ diff --git a/tests/integration/test_context_compile.py b/tests/integration/test_context_compile.py index c6c7055..c34b544 100644 --- a/tests/integration/test_context_compile.py +++ b/tests/integration/test_context_compile.py @@ -103,7 +103,7 @@ def seed_traceable_thread( ) person = store.create_entity( entity_type="person", - name="Samir", + name="Alex", source_memory_ids=[str(breakfast_memory["id"])], ) merchant = store.create_entity( diff --git a/tests/integration/test_entities_api.py b/tests/integration/test_entities_api.py index 4236c1f..a6fbe53 100644 --- a/tests/integration/test_entities_api.py +++ b/tests/integration/test_entities_api.py @@ -175,7 +175,7 @@ def test_entity_endpoints_list_and_get_entities_in_deterministic_user_scoped_ord created_entities = [ store.create_entity( entity_type="person", - name="Samir", + name="Alex", source_memory_ids=[str(seeded["memory_ids"][0])], ), store.create_entity( diff --git a/tests/integration/test_entity_edges_api.py b/tests/integration/test_entity_edges_api.py index d8ea5be..0f8c60c 100644 --- a/tests/integration/test_entity_edges_api.py +++ b/tests/integration/test_entity_edges_api.py @@ -128,7 +128,7 @@ def seed_entities( store = ContinuityStore(conn) person = store.create_entity( entity_type="person", - name="Samir", + name="Alex", source_memory_ids=[str(memory_ids[2])], ) merchant = store.create_entity( diff --git a/tests/unit/test_compiler.py b/tests/unit/test_compiler.py index 8df7a64..d966804 100644 --- a/tests/unit/test_compiler.py +++ b/tests/unit/test_compiler.py @@ -154,7 +154,7 @@ def test_compile_continuity_context_is_deterministic_and_stably_ordered() -> Non "id": entity_ids[0], "user_id": user_id, "entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": [str(memory_ids[0])], "created_at": base_time, }, @@ -479,7 +479,7 @@ def test_compile_continuity_context_records_included_and_excluded_reasons() -> N "id": dropped_entity_id, "user_id": user_id, "entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": [str(dropped_by_memory_limit_id)], "created_at": base_time, }, @@ -573,7 +573,7 @@ def test_compile_continuity_context_records_included_and_excluded_reasons() -> N "reason": "entity_limit_exceeded", "position": 1, "record_entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": [str(dropped_by_memory_limit_id)], } in trace_payloads assert { diff --git a/tests/unit/test_entity.py b/tests/unit/test_entity.py index c417b55..711ac0a 100644 --- a/tests/unit/test_entity.py +++ b/tests/unit/test_entity.py @@ -73,7 +73,7 @@ def test_create_entity_record_rejects_empty_source_memory_ids() -> None: user_id=uuid4(), entity=EntityCreateInput( entity_type="person", - name="Samir", + name="Alex", source_memory_ids=(), ), ) @@ -123,7 +123,7 @@ def test_list_entity_records_returns_deterministic_shape() -> None: second_memory_id = seed_memory(store) first_entity = store.create_entity( entity_type="person", - name="Samir", + name="Alex", source_memory_ids=[str(first_memory_id)], ) second_entity = store.create_entity( @@ -142,7 +142,7 @@ def test_list_entity_records_returns_deterministic_shape() -> None: { "id": str(first_entity["id"]), "entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": [str(first_memory_id)], "created_at": first_entity["created_at"].isoformat(), }, diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 7a71342..161d46a 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -3489,7 +3489,7 @@ def fake_user_connection(_database_url: str, _current_user_id): main_module.CreateEntityRequest( user_id=uuid4(), entity_type="person", - name="Samir", + name="Alex", source_memory_ids=[uuid4()], ) ) @@ -3769,7 +3769,7 @@ def fake_get_entity_record(store, *, user_id, entity_id): "entity": { "id": str(entity_id), "entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": ["memory-1"], "created_at": "2026-03-12T10:00:00+00:00", } @@ -3786,7 +3786,7 @@ def fake_get_entity_record(store, *, user_id, entity_id): "entity": { "id": str(entity_id), "entity_type": "person", - "name": "Samir", + "name": "Alex", "source_memory_ids": ["memory-1"], "created_at": "2026-03-12T10:00:00+00:00", } diff --git a/tests/unit/test_phase9_eval.py b/tests/unit/test_phase9_eval.py index 67adfc4..aecee1e 100644 --- a/tests/unit/test_phase9_eval.py +++ b/tests/unit/test_phase9_eval.py @@ -3,7 +3,11 @@ import json from pathlib import Path -from alicebot_api.retrieval_evaluation import calculate_phase9_metric_ratio, write_phase9_evaluation_report +from alicebot_api.retrieval_evaluation import ( + _public_source_path, + calculate_phase9_metric_ratio, + write_phase9_evaluation_report, +) def test_phase9_ratio_handles_zero_total() -> None: @@ -31,3 +35,14 @@ def test_phase9_report_writer_persists_json(tmp_path: Path) -> None: assert output_path.exists() saved = json.loads(output_path.read_text(encoding="utf-8")) assert saved == report + + +def test_public_source_path_uses_repo_relative_path_for_repo_files() -> None: + repo_fixture = Path("fixtures/openclaw/workspace_v1.json").resolve() + assert _public_source_path(repo_fixture) == "fixtures/openclaw/workspace_v1.json" + + +def test_public_source_path_redacts_external_paths(tmp_path: Path) -> None: + external = tmp_path / "sensitive-source.json" + external.write_text("{}", encoding="utf-8") + assert _public_source_path(external) == "external/sensitive-source.json"