diff --git a/src/scribe/mcp/tools/family.py b/src/scribe/mcp/tools/family.py index 8df85f05..206ad917 100644 --- a/src/scribe/mcp/tools/family.py +++ b/src/scribe/mcp/tools/family.py @@ -253,7 +253,6 @@ async def assess_family_adoption( reason: str, evidence: list[str] | None = None, precedent_ids: list[int] | None = None, - system_ids: list[int] | None = None, ) -> dict: """Answer one canon family idea for one project. YOU decide; nobody approves. Judge in this order and stop at the first that holds: @@ -268,8 +267,10 @@ async def assess_family_adoption( 3. adopted — it applies and the project does it. `evidence` names where (a file, a commit, a task, a CI run). 4. owed — none of the above. A task is filed in THIS project naming the - gap and the reference implementation for its language. Nothing edits - another repository; the project picks the task up itself. + gap and the reference implementation for its language, filed under + the project's System matching the idea's area (retag it with + update_task if that guess is wrong). Nothing edits another + repository; the project picks the task up itself. Read get_family_adoption first: answer consistently with its precedents unless this project differs in a way you can name in `reason`. The @@ -286,11 +287,10 @@ async def assess_family_adoption( reason: why — required for every outcome. evidence: where it is done (required for adopted), or what you checked. precedent_ids: earlier family decisions you followed, if any. - system_ids: Systems for an owed task. Omit to match the idea's own. """ return await adoption_svc.assess( current_user_id(), project_id, idea_id, outcome=outcome, reason=reason, - evidence=evidence, precedent_ids=precedent_ids, system_ids=system_ids, + evidence=evidence, precedent_ids=precedent_ids, ) diff --git a/src/scribe/services/family_adoption.py b/src/scribe/services/family_adoption.py index 72c6617f..493e9656 100644 --- a/src/scribe/services/family_adoption.py +++ b/src/scribe/services/family_adoption.py @@ -519,8 +519,7 @@ async def _matching_systems(session, project_id: int, note_ids: list[int]) -> li return list(dict.fromkeys(direct + list(mapped))) -async def _file_owed_task(user_id: int, row_id: int, reason: str, - system_ids: list[int] | None) -> Note: +async def _file_owed_task(user_id: int, row_id: int, reason: str) -> Note: from scribe.services import notes as notes_svc from scribe.services import systems as systems_svc @@ -531,7 +530,7 @@ async def _file_owed_task(user_id: int, row_id: int, reason: str, refs = await _references(session, row.idea_id) langs = await _project_languages(session, row.project_id) platforms = await family_svc._platform_slugs(session, row.idea_id) - systems = system_ids or await _matching_systems( + systems = await _matching_systems( session, row.project_id, [row.idea_id] + [r["id"] for r in refs]) project_id, idea_id, version = row.project_id, row.idea_id, idea.canon_version body = ( @@ -568,8 +567,7 @@ async def _set_task_status(user_id: int, task: Note, status: str, log: str) -> N await task_logs.create_log(user_id, task.id, log) -async def _sync_owed_task(user_id: int, row_id: int, *, reason: str, - system_ids: list[int] | None = None) -> dict | None: +async def _sync_owed_task(user_id: int, row_id: int, *, reason: str) -> dict | None: """Make the owed task agree with the answer. Idempotent: an `owed` row with an open task, or a settled row with a closed one, is left alone. A task the caller cannot write is left alone too, and said so.""" @@ -594,7 +592,7 @@ async def _sync_owed_task(user_id: int, row_id: int, *, reason: str, user_id, task, TaskStatus.todo.value, f"Reopened: family idea #{idea_id} was assessed owed again — {reason}") return ref(task, TaskStatus.todo.value, "reopened") - task = await _file_owed_task(user_id, row_id, reason, system_ids) + task = await _file_owed_task(user_id, row_id, reason) async with async_session() as session: row = await session.get(FamilyAdoption, row_id) row.owed_task_id = task.id @@ -645,7 +643,7 @@ def _answer(row: FamilyAdoption, *, status: str, reason: str, version: int, async def assess( user_id: int, project_id: int, idea_id: int, *, outcome: str, reason: str, evidence: list[str] | None = None, precedent_ids: list[int] | None = None, - system_ids: list[int] | None = None, decided_via: str = "agent", + decided_via: str = "agent", ) -> dict: """Record one project's answer to one canon idea. @@ -692,7 +690,7 @@ async def assess( if decision is not None: await session.refresh(decision) row_id = row.id - task = await _sync_owed_task(user_id, row_id, reason=reason, system_ids=system_ids) + task = await _sync_owed_task(user_id, row_id, reason=reason) rows = await list_adoptions(user_id, project_id=project_id, idea_id=idea_id) return { "changed": changed, diff --git a/tests/test_family_adoption.py b/tests/test_family_adoption.py index 63a59636..585872ef 100644 --- a/tests/test_family_adoption.py +++ b/tests/test_family_adoption.py @@ -62,7 +62,7 @@ GOOD = { @pytest.mark.parametrize("ground", CONFLICT_KEYS) def test_each_ground_holds_when_its_needs_are_met(ground): - kw = dict(evidence=None, conditions=None, **{**GOOD[ground]}) + kw = {"evidence": None, "conditions": None, **GOOD[ground]} assert conflict_problems(ground=ground, grounds_checked=_checked(ground), fold="their reasoning", **kw) == []