docs(01.1): create phase plan
This commit is contained in:
parent
0f4ecc3c88
commit
4653ae877a
4 changed files with 479 additions and 4 deletions
|
|
@ -28,13 +28,15 @@ Plans:
|
|||
|
||||
### Phase 01.1: Matrix restart reconciliation and dev reset workflow (INSERTED)
|
||||
|
||||
**Goal:** [Urgent work - to be planned]
|
||||
**Requirements**: TBD
|
||||
**Goal:** Сделать Matrix-адаптер пригодным для повторяемого локального рестарта и ручного QA: бот восстанавливает минимальный local state из существующих Space/rooms и даёт явный dev reset workflow вместо ручного ritual reset.
|
||||
**Requirements**: none explicitly mapped
|
||||
**Depends on:** Phase 1
|
||||
**Plans:** 0 plans
|
||||
**Plans:** 3 plans
|
||||
|
||||
Plans:
|
||||
- [ ] TBD (run /gsd:plan-phase 01.1 to break down)
|
||||
- [ ] 01.1-01-PLAN.md — Non-destructive Matrix reconciliation module and tests
|
||||
- [ ] 01.1-02-PLAN.md — Wire startup/bootstrap recovery into the Matrix runtime
|
||||
- [ ] 01.1-03-PLAN.md — Dev reset CLI and updated Matrix restart runbook
|
||||
|
||||
### Phase 2: SDK Integration
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
---
|
||||
phase: 01.1-matrix-restart-reconciliation-and-dev-reset-workflow
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- adapter/matrix/reconcile.py
|
||||
- tests/adapter/matrix/test_reconcile.py
|
||||
autonomous: true
|
||||
requirements: []
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "A normal Matrix restart can rebuild missing local metadata from already joined Space/chat rooms instead of requiring a destructive reset."
|
||||
- "Reconciliation restores the minimal local state needed for routing and chat operations: `matrix_user:*`, `matrix_room:*`, and missing `chat:{user}:{chat_id}` rows."
|
||||
- "Reconciliation never provisions new Matrix rooms or Spaces while repairing local state."
|
||||
- "Recovered users get `next_chat_index` advanced past the highest recovered `C*` chat id."
|
||||
artifacts:
|
||||
- path: "adapter/matrix/reconcile.py"
|
||||
provides: "Matrix bootstrap reconciliation helpers and structured report objects."
|
||||
- path: "tests/adapter/matrix/test_reconcile.py"
|
||||
provides: "Regression coverage for startup and single-room reconciliation behavior."
|
||||
key_links:
|
||||
- from: "adapter/matrix/reconcile.py"
|
||||
to: "adapter/matrix/store.py"
|
||||
via: "set_user_meta and set_room_meta restore Matrix metadata"
|
||||
pattern: "set_(user|room)_meta"
|
||||
- from: "adapter/matrix/reconcile.py"
|
||||
to: "core/chat.py"
|
||||
via: "chat_mgr.get_or_create repairs missing `chat:*` rows"
|
||||
pattern: "chat_mgr\\.get_or_create"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create the non-destructive Matrix reconciliation layer that Phase 01.1 depends on.
|
||||
|
||||
Purpose: Per D-01 through D-07, the adapter must stop treating local SQLite state as the only truth in dev. Startup and recovery code need a single helper module that can rebuild local metadata from the homeserver room graph without creating duplicate Spaces or chats.
|
||||
Output: `adapter/matrix/reconcile.py` with full-run and single-room recovery helpers, plus targeted pytest coverage.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/Users/a/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@/Users/a/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md
|
||||
@.planning/phases/01-matrix-qa-polish/01-01-SUMMARY.md
|
||||
@adapter/matrix/store.py
|
||||
@adapter/matrix/handlers/auth.py
|
||||
@core/chat.py
|
||||
@tests/adapter/matrix/test_invite_space.py
|
||||
|
||||
<interfaces>
|
||||
From `adapter/matrix/store.py`:
|
||||
|
||||
```python
|
||||
async def get_room_meta(store: StateStore, room_id: str) -> dict | None
|
||||
async def set_room_meta(store: StateStore, room_id: str, meta: dict) -> None
|
||||
async def get_user_meta(store: StateStore, matrix_user_id: str) -> dict | None
|
||||
async def set_user_meta(store: StateStore, matrix_user_id: str, meta: dict) -> None
|
||||
```
|
||||
|
||||
From `core/chat.py`:
|
||||
|
||||
```python
|
||||
async def get_or_create(
|
||||
self,
|
||||
user_id: str,
|
||||
chat_id: str,
|
||||
platform: str,
|
||||
surface_ref: str,
|
||||
name: str | None = None,
|
||||
) -> ChatContext
|
||||
```
|
||||
|
||||
From Phase 01 room metadata shape:
|
||||
|
||||
```python
|
||||
{
|
||||
"room_type": "chat",
|
||||
"chat_id": "C4",
|
||||
"display_name": "Чат 4",
|
||||
"matrix_user_id": "@alice:example.org",
|
||||
"space_id": "!space:example.org",
|
||||
}
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Add reconciliation module for startup and single-room recovery</name>
|
||||
<files>adapter/matrix/reconcile.py, tests/adapter/matrix/test_reconcile.py</files>
|
||||
<read_first>adapter/matrix/store.py, adapter/matrix/handlers/auth.py, core/chat.py, tests/adapter/matrix/test_invite_space.py, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md</read_first>
|
||||
<behavior>
|
||||
- Test 1: `reconcile_matrix_state(...)` recreates missing `matrix_user:*`, `matrix_room:*`, and `chat:*` entries from joined Matrix rooms without calling `room_create`.
|
||||
- Test 2: `reconcile_matrix_state(...)` leaves already-correct local metadata intact and reports restored vs skipped/conflicting rooms.
|
||||
- Test 3: `reconcile_single_room(...)` can repair one `unregistered:{room_id}` chat room on demand and recompute `next_chat_index` for that user.
|
||||
- Test 4: Space rooms or unrelated joined rooms are skipped, not converted into chat rows.
|
||||
</behavior>
|
||||
<action>
|
||||
Create `adapter/matrix/reconcile.py` as the authoritative recovery module for this phase. Implement a small, explicit API that Plan 02 can wire directly:
|
||||
|
||||
```python
|
||||
async def reconcile_matrix_state(client: Any, store: StateStore, chat_mgr: ChatManager) -> dict: ...
|
||||
async def reconcile_single_room(
|
||||
client: Any, store: StateStore, chat_mgr: ChatManager, room_id: str, matrix_user_id: str
|
||||
) -> dict: ...
|
||||
```
|
||||
|
||||
Inside this module, add focused private helpers as needed for room classification, extracting room names, parsing `C<number>` ids, and recomputing `next_chat_index`. Keep the logic non-destructive per D-04:
|
||||
- never call `room_create`, `room_invite`, or provisioning code from `handlers/auth.py`
|
||||
- prefer already-hydrated room data from the post-sync client object, and only fall back to explicit room-state fetches if required for room classification
|
||||
- rebuild only the minimal metadata required by D-03: `matrix_user:*`, `matrix_room:*`, and missing `chat:{user}:{chat_id}` records
|
||||
- if `chat:*` exists but points at the wrong `surface_ref`, repair it from Matrix room metadata and include the fix in the returned report
|
||||
- derive `next_chat_index` from the highest recovered `C<number>` for that user instead of trusting stale local counters
|
||||
|
||||
Return a structured reconciliation report with stable keys such as:
|
||||
`joined_rooms`, `restored_user_meta`, `restored_room_meta`, `restored_chat_rows`, `repaired_chat_rows`, `skipped_rooms`, and `conflicts`.
|
||||
|
||||
Write `tests/adapter/matrix/test_reconcile.py` with lightweight `SimpleNamespace`/fake-client fixtures following the existing Matrix test style. Cover both full startup reconciliation and `reconcile_single_room(...)`. Assert that no provisioning calls are made during reconciliation, because D-04 forbids creating new Space/room topology while recovering local state.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /Users/a/MAI/sem2/lambda/surfaces-bot && pytest tests/adapter/matrix/test_reconcile.py -q</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `adapter/matrix/reconcile.py` exports `reconcile_matrix_state` and `reconcile_single_room`.
|
||||
- Reconciliation restores missing `matrix_user:*`, `matrix_room:*`, and `chat:*` entries for already-joined Matrix chat rooms per D-02 and D-03.
|
||||
- Reconciliation does not call `room_create` or otherwise provision new server-side rooms per D-04.
|
||||
- The report returned by reconciliation clearly distinguishes restored items, skipped rooms, and conflicts.
|
||||
- `tests/adapter/matrix/test_reconcile.py` proves `next_chat_index` is recomputed from recovered chat ids rather than stale local state.
|
||||
</acceptance_criteria>
|
||||
<done>The repository has an executable, tested reconciliation layer that can rebuild local Matrix metadata after dev-state loss without duplicating server-side rooms.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Run `pytest tests/adapter/matrix/test_reconcile.py -q` and confirm startup and single-room reconciliation paths are covered.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Matrix recovery logic exists as a dedicated module instead of being scattered through handlers.
|
||||
- Reconciliation is idempotent, non-destructive, and sufficient to restore routing/chat metadata from existing Matrix rooms.
|
||||
- Plan 02 can wire startup and first-access recovery by calling exported functions rather than inventing new recovery logic.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-01-SUMMARY.md`
|
||||
</output>
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
---
|
||||
phase: 01.1-matrix-restart-reconciliation-and-dev-reset-workflow
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["01.1-01"]
|
||||
files_modified:
|
||||
- adapter/matrix/bot.py
|
||||
- tests/adapter/matrix/test_dispatcher.py
|
||||
autonomous: true
|
||||
requirements: []
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "The Matrix bot performs an initial sync and reconciliation before entering steady-state `sync_forever()`."
|
||||
- "If a room still arrives as `unregistered:{room_id}` after startup, the bot makes one targeted recovery attempt before dispatching or failing."
|
||||
- "When reconciliation cannot repair a room, the bot logs a clear diagnostic reason instead of crashing on downstream commands like `!rename`."
|
||||
artifacts:
|
||||
- path: "adapter/matrix/bot.py"
|
||||
provides: "Startup bootstrap flow with initial sync, reconciliation, and targeted runtime retry."
|
||||
- path: "tests/adapter/matrix/test_dispatcher.py"
|
||||
provides: "Matrix runtime coverage for pre-sync reconcile and on-message recovery behavior."
|
||||
key_links:
|
||||
- from: "adapter/matrix/bot.py"
|
||||
to: "adapter/matrix/reconcile.py"
|
||||
via: "startup bootstrap and single-room recovery calls"
|
||||
pattern: "reconcile_(matrix_state|single_room)"
|
||||
- from: "adapter/matrix/bot.py"
|
||||
to: "adapter/matrix/room_router.py"
|
||||
via: "unregistered room detection before dispatch"
|
||||
pattern: "unregistered:"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Wire the new reconciliation layer into the actual Matrix runtime.
|
||||
|
||||
Purpose: D-05 through D-07 require restart recovery to be the default developer path. The bot must bootstrap itself from existing Matrix rooms on startup and make one on-demand repair attempt before routing an unknown room through the dispatcher.
|
||||
Output: `adapter/matrix/bot.py` performs initial sync + reconciliation before `sync_forever()`, and runtime tests prove the bot recovers or logs clearly instead of blindly dispatching broken state.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/Users/a/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@/Users/a/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-01-PLAN.md
|
||||
@adapter/matrix/bot.py
|
||||
@adapter/matrix/room_router.py
|
||||
@adapter/matrix/reconcile.py
|
||||
@tests/adapter/matrix/test_dispatcher.py
|
||||
|
||||
<interfaces>
|
||||
From `adapter/matrix/bot.py`:
|
||||
|
||||
```python
|
||||
class MatrixBot:
|
||||
async def on_room_message(self, room: MatrixRoom, event: RoomMessageText) -> None
|
||||
|
||||
async def main() -> None
|
||||
```
|
||||
|
||||
From `adapter/matrix/reconcile.py`:
|
||||
|
||||
```python
|
||||
async def reconcile_matrix_state(client: Any, store: StateStore, chat_mgr: ChatManager) -> dict
|
||||
async def reconcile_single_room(
|
||||
client: Any, store: StateStore, chat_mgr: ChatManager, room_id: str, matrix_user_id: str
|
||||
) -> dict
|
||||
```
|
||||
|
||||
From `adapter/matrix/room_router.py`:
|
||||
|
||||
```python
|
||||
async def resolve_chat_id(store: StateStore, room_id: str, matrix_user_id: str) -> str
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Run initial sync and reconciliation before the long-poll loop</name>
|
||||
<files>adapter/matrix/bot.py, tests/adapter/matrix/test_dispatcher.py</files>
|
||||
<read_first>adapter/matrix/bot.py, adapter/matrix/reconcile.py, tests/adapter/matrix/test_dispatcher.py, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md</read_first>
|
||||
<behavior>
|
||||
- Test 1: `main()` performs `client.sync(timeout=0, full_state=True)` before `sync_forever()`.
|
||||
- Test 2: `main()` calls `reconcile_matrix_state(...)` after the initial sync and logs the returned report.
|
||||
- Test 3: startup still reaches `sync_forever()` when reconciliation reports recoverable skips/conflicts instead of fatal failure.
|
||||
</behavior>
|
||||
<action>
|
||||
Modify `adapter/matrix/bot.py` so normal startup follows the two-phase bootstrap recommended in research:
|
||||
1. build client and runtime
|
||||
2. authenticate
|
||||
3. register callbacks
|
||||
4. run `await client.sync(timeout=0, full_state=True)`
|
||||
5. run `await reconcile_matrix_state(client, runtime.store, runtime.chat_mgr)`
|
||||
6. log a structured `matrix_reconcile_complete` event with the report fields
|
||||
7. enter `await client.sync_forever(timeout=30000)`
|
||||
|
||||
Do not move provisioning logic into startup. The startup step only rehydrates local state from server-side rooms per D-02 through D-04.
|
||||
|
||||
Update or add focused tests in `tests/adapter/matrix/test_dispatcher.py` using `monkeypatch`/fake-client patterns already used in the repo so the verify command proves the call order and logging-safe behavior. The test should fail if `sync_forever()` starts before reconciliation.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /Users/a/MAI/sem2/lambda/surfaces-bot && pytest tests/adapter/matrix/test_dispatcher.py -q</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `adapter/matrix/bot.py` runs an initial full-state sync before steady-state polling.
|
||||
- `adapter/matrix/bot.py` invokes `reconcile_matrix_state(...)` exactly once during startup.
|
||||
- Startup logs a structured reconciliation summary instead of silently skipping the recovery step.
|
||||
- `tests/adapter/matrix/test_dispatcher.py` asserts the bootstrap order explicitly.
|
||||
</acceptance_criteria>
|
||||
<done>Normal Matrix bot startup now includes a recovery pass before the event loop begins handling user traffic.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Retry unknown-room routing once before dispatching broken state</name>
|
||||
<files>adapter/matrix/bot.py, tests/adapter/matrix/test_dispatcher.py</files>
|
||||
<read_first>adapter/matrix/bot.py, adapter/matrix/room_router.py, adapter/matrix/reconcile.py, tests/adapter/matrix/test_dispatcher.py, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md</read_first>
|
||||
<behavior>
|
||||
- Test 1: `MatrixBot.on_room_message(...)` detects `unregistered:{room_id}`, runs `reconcile_single_room(...)`, then retries `resolve_chat_id(...)`.
|
||||
- Test 2: if retry succeeds, the event is dispatched against the recovered logical chat id.
|
||||
- Test 3: if retry still fails, the bot does not crash; it logs a clear warning and sends a user-facing diagnostic message to that room.
|
||||
</behavior>
|
||||
<action>
|
||||
Extend `MatrixBot.on_room_message(...)` so D-07 is satisfied even when startup could not repair a room yet. Keep `resolve_chat_id(...)` as the room-router source of truth, but treat `unregistered:{room_id}` as a recovery trigger rather than a stable runtime identity:
|
||||
- first call `resolve_chat_id(...)`
|
||||
- if the result starts with `unregistered:`, call `reconcile_single_room(client, runtime.store, runtime.chat_mgr, room.room_id, event.sender)`
|
||||
- immediately retry `resolve_chat_id(...)`
|
||||
- only dispatch once a concrete logical chat id exists
|
||||
- if the retry still returns `unregistered:{room_id}`, log a structured warning with room id, matrix user id, and reconciliation report, then send a short `OutgoingMessage`-equivalent Matrix text explaining that local state could not be restored automatically and a dev reset/restart may be required
|
||||
|
||||
Do not invent a new fallback chat id and do not auto-create rooms here; that would violate D-04. Keep this change inside `adapter/matrix/bot.py` so file ownership stays isolated for this plan.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /Users/a/MAI/sem2/lambda/surfaces-bot && pytest tests/adapter/matrix/test_dispatcher.py -q</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- Unknown Matrix rooms trigger one targeted reconciliation attempt before dispatch.
|
||||
- Successful targeted recovery leads to normal dispatch with a real logical `chat_id`.
|
||||
- Failed targeted recovery logs a clear diagnostic and avoids a handler crash on missing chat state per D-06.
|
||||
- No code path in this task provisions new Matrix rooms or Spaces.
|
||||
</acceptance_criteria>
|
||||
<done>The runtime treats unknown rooms as recoverable state drift first, not as a silent routing failure or crash path.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Run `pytest tests/adapter/matrix/test_dispatcher.py -q` and confirm both startup-bootstrap and first-access recovery behaviors are covered.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- A standard Matrix restart now attempts recovery before the bot starts processing live events.
|
||||
- Unknown-room events are diagnosable and recoverable instead of falling straight into broken command handling.
|
||||
- The runtime never provisions new server-side rooms during restart reconciliation.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-02-SUMMARY.md`
|
||||
</output>
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
---
|
||||
phase: 01.1-matrix-restart-reconciliation-and-dev-reset-workflow
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- adapter/matrix/reset.py
|
||||
- tests/adapter/matrix/test_reset.py
|
||||
- README.md
|
||||
autonomous: true
|
||||
requirements: []
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Developers have an explicit dev-only reset command instead of relying on memory or ad hoc shell history."
|
||||
- "The default reset mode clears only local Matrix state and explains the manual Matrix-client cleanup that may still be needed."
|
||||
- "Optional server cleanup is clearly named around leave/forget semantics and supports dry-run output."
|
||||
artifacts:
|
||||
- path: "adapter/matrix/reset.py"
|
||||
provides: "Dev reset CLI for local-only, server-leave-forget, and dry-run workflows."
|
||||
- path: "tests/adapter/matrix/test_reset.py"
|
||||
provides: "CLI coverage for local reset behavior and printed operator guidance."
|
||||
- path: "README.md"
|
||||
provides: "Updated developer instructions for normal restart vs explicit reset."
|
||||
key_links:
|
||||
- from: "adapter/matrix/reset.py"
|
||||
to: "README.md"
|
||||
via: "documented invocation and manual Matrix cleanup guidance"
|
||||
pattern: "adapter\\.matrix\\.reset"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Ship the dev reset workflow that complements normal restart reconciliation.
|
||||
|
||||
Purpose: D-08 through D-10 require a repeatable, explicit reset path for clean-room QA without making destructive cleanup the default restart flow. This plan creates the tool and updates the runbook developers actually use.
|
||||
Output: `adapter/matrix/reset.py`, pytest coverage, and README instructions that replace the old `rm -f lambda_matrix.db` ritual.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/Users/a/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@/Users/a/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md
|
||||
@.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md
|
||||
@README.md
|
||||
@adapter/matrix/bot.py
|
||||
@core/store.py
|
||||
|
||||
<interfaces>
|
||||
From `adapter/matrix/bot.py` env usage:
|
||||
|
||||
```python
|
||||
db_path = os.environ.get("MATRIX_DB_PATH", "lambda_matrix.db")
|
||||
store_path = os.environ.get("MATRIX_STORE_PATH", "matrix_store")
|
||||
homeserver = os.environ.get("MATRIX_HOMESERVER")
|
||||
user_id = os.environ.get("MATRIX_USER_ID")
|
||||
```
|
||||
|
||||
From `core/store.py`:
|
||||
|
||||
```python
|
||||
class SQLiteStore:
|
||||
def __init__(self, db_path: str) -> None: ...
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Add a dev-only Matrix reset CLI with explicit modes</name>
|
||||
<files>adapter/matrix/reset.py, tests/adapter/matrix/test_reset.py</files>
|
||||
<read_first>adapter/matrix/bot.py, core/store.py, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md</read_first>
|
||||
<behavior>
|
||||
- Test 1: `--mode local-only` deletes the configured local DB/store paths or reports what would be deleted in dry-run mode.
|
||||
- Test 2: `--mode server-leave-forget --dry-run` prints the exact rooms it would leave/forget and does not mutate local files.
|
||||
- Test 3: when server cleanup is not executed, the command prints the manual Matrix-client steps required by D-10.
|
||||
</behavior>
|
||||
<action>
|
||||
Create `adapter/matrix/reset.py` as a CLI entrypoint runnable via `uv run python -m adapter.matrix.reset`. Use `argparse` and keep the tool explicitly dev-only in its help text and logs.
|
||||
|
||||
Implement the following modes from research and locked decisions:
|
||||
- `local-only` (default destructive mode for local QA): remove `MATRIX_DB_PATH` and `MATRIX_STORE_PATH` if they exist; if not, report that they were already absent
|
||||
- `server-leave-forget`: for the bot account only, log in using the same Matrix env vars as `adapter/matrix/bot.py`, inspect joined rooms, and call `room_leave()` + `room_forget()` for each joined room; support `--dry-run` so the operator can inspect the target set before mutation
|
||||
- `--dry-run` must work with both modes and print a structured summary instead of mutating files or Matrix membership
|
||||
|
||||
Always print a post-run summary that distinguishes:
|
||||
- what local files/directories were deleted or would be deleted
|
||||
- what server-side leave/forget actions were executed or would be executed
|
||||
- the manual Matrix client steps still required for a true clean-room QA rerun (leave/archive old rooms or Space in Element, accept fresh invites, etc.) when those actions are outside this phase
|
||||
|
||||
Write `tests/adapter/matrix/test_reset.py` to cover local-only deletion, dry-run output, and server-leave-forget dry-run behavior with fake clients/temporary directories. Follow the repo’s existing lightweight async test style.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /Users/a/MAI/sem2/lambda/surfaces-bot && pytest tests/adapter/matrix/test_reset.py -q</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `adapter/matrix/reset.py` supports `local-only`, `server-leave-forget`, and `--dry-run`.
|
||||
- `local-only` reset targets both `lambda_matrix.db` and `matrix_store` via env-aware paths per D-09.
|
||||
- The tool never claims to globally delete Matrix rooms; it uses leave/forget semantics or prints manual cleanup instructions per D-10.
|
||||
- `tests/adapter/matrix/test_reset.py` proves dry-run mode is non-destructive.
|
||||
</acceptance_criteria>
|
||||
<done>The repository contains a repeatable dev reset tool that replaces the undocumented shell ritual and names server-side cleanup honestly.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Replace the README reset ritual with the new restart and reset workflow</name>
|
||||
<files>README.md</files>
|
||||
<read_first>README.md, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md</read_first>
|
||||
<action>
|
||||
Update `README.md` so Matrix development instructions reflect Phase 01.1 instead of the old destructive reset ritual. Replace the current manual QA block that tells developers to `rm -f lambda_matrix.db` with a short, explicit split:
|
||||
- normal restart: `PYTHONPATH=. uv run python -m adapter.matrix.bot` now performs reconciliation automatically
|
||||
- explicit clean-room reset: `PYTHONPATH=. uv run python -m adapter.matrix.reset --mode local-only`
|
||||
- optional server cleanup preview: `PYTHONPATH=. uv run python -m adapter.matrix.reset --mode server-leave-forget --dry-run`
|
||||
|
||||
State clearly that normal restart is the default path per D-05, and that full server-side cleanup may still require manual steps in the Matrix client. Keep the README concise; do not add production guidance or Phase 2 SDK content.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /Users/a/MAI/sem2/lambda/surfaces-bot && python -m adapter.matrix.reset --help >/tmp/matrix-reset-help.txt && rg -n "adapter.matrix.reset|local-only|server-leave-forget|reconciliation" README.md /tmp/matrix-reset-help.txt</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `README.md` no longer recommends raw `rm -f lambda_matrix.db` as the default Matrix restart workflow.
|
||||
- `README.md` documents the normal restart path and the explicit reset path separately.
|
||||
- The documented reset commands match the CLI implemented in `adapter/matrix/reset.py`.
|
||||
</acceptance_criteria>
|
||||
<done>Developers can follow a repeatable README workflow for ordinary restart and clean-room QA reset without relying on tribal knowledge.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Run `pytest tests/adapter/matrix/test_reset.py -q` and `python -m adapter.matrix.reset --help`, then confirm the README commands and help text stay aligned.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Dev reset is an explicit tool, not a remembered shell sequence.
|
||||
- Local-only reset is automated and documented.
|
||||
- Server cleanup semantics are honest, dry-runnable, and accompanied by manual Matrix-client guidance where needed.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-03-SUMMARY.md`
|
||||
</output>
|
||||
Loading…
Add table
Add a link
Reference in a new issue