feat(409): a task write returns where the task sits (#4010)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 57s
CI & Build / Python tests (push) Successful in 1m30s
CI & Build / Build & push image (push) Successful in 27s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 57s
CI & Build / Python tests (push) Successful in 1m30s
CI & Build / Build & push image (push) Successful in 27s
Step 1 of milestone 409 "Response shapes". An agent reporting finished work
is asked to say which milestone it belongs to, which step of how many, and
what is next. Without those facts to hand it reconstructs them, and a
reconstruction reads exactly like the truth when it is wrong.
create_task and update_task (MCP) and the REST create/update task routes now
return a placement block: project; and for a task in a milestone, the
milestone, position {step, of}, progress {completed, total, pct} and next
(the next open step, falling back to the earliest open one before it).
- Step order is creation order, not get_milestone listing order, which
reshuffles on every update.
- Siblings are read through readable_notes_clause; position and progress
are computed over that same readable set, so a collaborator is never shown
a step title they cannot open, and a note share alone reveals no plan.
- Fail-open and omitted when empty, like every in-band decoration.
- _no_embedding moves into conftest as one opt-in fixture for both
integration modules that need it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ from scribe.services import notes as notes_svc
|
||||
# avoid the database would otherwise stub the validation too — turning a
|
||||
# guard into a MagicMock that approves anything.
|
||||
from scribe.services.notes import minted_kind
|
||||
from scribe.services import placement as placement_svc
|
||||
from scribe.services import planning as planning_svc
|
||||
from scribe.services import record_batch as batch_svc
|
||||
from scribe.services import rulebooks as rulebooks_svc
|
||||
@@ -185,7 +186,7 @@ async def create_task(
|
||||
|
||||
Returns the created task, OR — when a near-duplicate is found and force is
|
||||
false — {"duplicate": true, "existing_id": ..., "message": ...} (nothing
|
||||
created). A tagged record shows its `systems`; created untagged in a
|
||||
created). A task in a project carries `placement` (see update_task). A tagged record shows its `systems`; created untagged in a
|
||||
project, the response carries the `systems_hint` question instead —
|
||||
answer it: tag the record, create the missing System, or deliberately
|
||||
leave it untagged.
|
||||
@@ -223,7 +224,7 @@ async def create_task(
|
||||
await systems_svc.set_record_systems(uid, note.id, system_ids)
|
||||
data = note.to_dict()
|
||||
await systems_tools.attach_systems(uid, uid, data, note.id, project_id or None)
|
||||
return data
|
||||
return await placement_svc.attach_placement(uid, data, note)
|
||||
|
||||
|
||||
async def update_task(
|
||||
@@ -262,6 +263,14 @@ async def update_task(
|
||||
work that becomes an investigation should say so. 'plan' is
|
||||
refused: plans are milestones (start_planning), and the value
|
||||
survives only so historical plan-tasks stay writable.
|
||||
|
||||
The response carries `placement` for a task in a project: its `project`,
|
||||
and for a task in a milestone its `milestone`, `position` ({step, of}),
|
||||
`progress` ({completed, total, pct}) and `next` (the next open step, or
|
||||
null). These are the facts to use when telling the operator where the
|
||||
work sits and what comes next — read them from here rather than
|
||||
reconstructing them, because a remembered milestone title or "next step"
|
||||
reads exactly like a real one when it is wrong.
|
||||
"""
|
||||
uid = current_user_id()
|
||||
fields: dict = {}
|
||||
@@ -299,7 +308,7 @@ async def update_task(
|
||||
await systems_tools.attach_systems(
|
||||
uid, getattr(note, "user_id", uid) or uid, data, task_id, note.project_id
|
||||
)
|
||||
return data
|
||||
return await placement_svc.attach_placement(uid, data, note)
|
||||
|
||||
|
||||
async def add_task_log(task_id: int, content: str) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user