Repository navigation
Ship approved conversational todo creation #126
Description
Ship approved conversational todo creation
Status: source implementation, independent verification, PM acceptance, commits, and original default-off deployment are complete; accepted #179/#168 canonical Task/Card follow-ups are committed on local main but unpushed/unshipped, and the only remaining #126 outcome is the HUMAN text/todo subset owned by #128 after #166/#182
Tags: enhancement, assistant, work-engine, backend, infra, testing, data, human, P1
Parent: #122
Depends on: #121/#124/#125 source and default-off prerequisites are satisfied; accepted #179 commit 02ee455efad09865ecdbd578e940c59e0bf7dc36 and #168 commit 41dca9e3748fe627c195f48a7f97ae203b343f60 define the canonical Task version/history and Card lifecycle contract and are local-only; live evidence waits for #166 A/B/C → #182 final preflight → D → cleanup and one ordinary all-off deploy
Blocks: live-acceptance closure only; #128 owns the integrated rollout and #126 is not a source blocker
Next owner: the #166 orchestrator/credentialed operator through the reviewed storage sequence; then the authorized HUMAN Telegram/provider owner with On-Call through #128; PM closes #126 after the bounded sanitized todo cross-post passes
Resume condition: #166/#182 record accepted sandbox outcomes, canonical writers reopen on the final empty Tasks schema with the accepted #179/#168 commits, temporary phase controls are deleted, ordinary push-triggered OIDC deployment is restored, and one normal main all-off run succeeds; then #128 may run its Text + todo stage
Architecture: _docs/CONVERSATIONAL_AGENT_PLUGIN_ARCHITECTURE.md at 4e5402c
Current review state
c47c5258a08b29c7c5ea6e797149c8a6619bbe71and SAM portability follow-upc8d153cf1ddb07acca6846182b4f65af9338b6ffare accepted ancestors oforigin/main. The static runtime registry/plugin, strict proposal, capability-limited writer, recovery, result delivery, tests, SAM resources, and default-off controls are source-complete.- Roll out and cut over the Telegram conversational MVP #128 rollout commit
9595361a0546a52a5cb90ace7df0bbdeb524866ais also integrated. Normal OIDC runs 31545689094 and 31711997388 reached successful all-off deploy/seed/smoke outcomes. This proves the dark path and fail-closed configuration; it is not a live Telegram, model, approval, or Task-write result. - Accepted Prevent lost Task updates and history with optimistic concurrency #179 commit
02ee455efad09865ecdbd578e940c59e0bf7dc36makes every new todo Task canonical atversion: 1withtaskHistory: []. Accepted Complete and archive cards automatically when all tasks are done #168 commit41dca9e3748fe627c195f48a7f97ae203b343f60keeps the todo writer and portable contract inside the strict canonical Task/Card lifecycle. Both are ancestors of current localmainbut absent fromorigin/main; neither is shipped or active in the sandbox. - No live Telegram todo journey, z.ai invocation, approval, Task creation, duplicate-delivery proof, or rollback has run.
#126 closure subset delegated to #128
After #166 repaired A/B/C → #182 final no-replacement Cards preflight → reviewed D → cleanup and one following ordinary all-off deployment:
- Enable only Roll out and cut over the Telegram conversational MVP #128 Text + todo through one normal OIDC stack update: Telegram ingress on, execution on, plugins exactly
todo, Typefully external execution off, voice off, photo off. - One linked active operator in a private Telegram chat sends an ordinary todo request, answers one missing/ambiguous-field clarification, requests one revision, and approves the exact current Berlin date-only preview. No Task may exist before that approval.
- Prove exactly one actor-owned Task and one private result. The Task must match the approved description/date and fixed
status=todo,source=conversational-agent, actor ownership, safe assistant provenance,version=1, andtaskHistory=[]; it must read cleanly under the accepted Prevent lost Task updates and history with optimistic concurrency #179/Complete and archive cards automatically when all tasks are done #168 canonical contract. - Repeat the approval/delivery path and prove convergence on the same Task/result with no second Task. Send
/todoand prove static guidance with no proposal, provider call, writer call, or Task. - Cross-post only sanitized IDs/hashes, counts, states, and timestamps to Ship approved conversational todo creation #126. Do not post chat text, Telegram identity, secret/provider configuration, prompt/completion, or task contents beyond a synthetic/sanitized field-match statement.
This bounded text/todo proof is the only remaining #126 criterion. Live voice/photo, Typefully preview/effect, unrelated alarm canaries, and completion of the full #128 rollback matrix are not #126 closure requirements. A failed stage stops progression under #128; it does not authorize replay of an unknown effect, queue purge, Task deletion, manual Lambda patch, migration, import, export, or restore.
Product decisions
This is the first complete production mutation through the conversational framework. It creates exactly one ordinary todo task in the authenticated actor's own scope after an exact preview and core approval.
Keep the first todo schema deliberately small:
description: required normalized plain text, 1–500 characters
date: required valid YYYY-MM-DD calendar date
The resulting task always has status=todo, assigneeId=<authenticated DataOps user>, createdBy=<same user>, and source=conversational-agent. The plugin cannot choose another assignee, status, owner, bundle, recurring rule, time, reminder, waiting state, tags, links, documents, proof fields, or arbitrary task properties.
DataOps operational dates use Europe/Berlin for this MVP. The runtime gives the model the current Berlin calendar date. Relative dates may be resolved to an exact date only when unambiguous; the exact date and timezone are shown in the preview. If the date is missing or ambiguous, ask. If a request contains a specific time, explain that this MVP stores a date only and ask the user to confirm the date-only todo instead of silently dropping the time.
There is no /todo mutation command. /todo with or without arguments returns a short static instruction to describe the task in an ordinary private message and invokes neither the model nor task writer.
Do not route execution through the generic POST /api/tasks handler or the current unrestricted createTask(client, Record<string, unknown>) function. Add a narrow actor-owned todo writer used only by the durable execution worker. Existing task API behavior remains compatible.
An internal DynamoDB task write is recoverable by deterministic identity and conditional creation. If the task commit succeeds but the worker loses its response, do not delete or compensate the task; recovery returns the same task and completes the original attempt. This is safer and simpler than an automatic rollback that could remove a visible task.
Operator journey
-
A linked, active user sends an ordinary message in a Telegram private chat, for example: “Remind me to follow up with Jane next Tuesday.”
-
The Consolidate private Telegram identity, text, voice, and photo input #121 adapter records the event and passes text—or already confirmed voice/photo-derived text—to the Build the static plugin runtime and z.ai conversational adapter #125 runtime.
-
The runtime loads the registered
todoplugin in turn one and invokes its strictpropose_createaction in the separate turn two. -
The plugin asks only for missing or ambiguous description/date information. It never creates a task during clarification.
-
The bot presents one normalized todo:
Todo Task: Follow up with Jane Date: 2026-08-04 (Europe/Berlin, date only) Assignee: You Status: Todo -
Core controls are Approve todo, Request changes, Cancel proposal, and Discard draft.
-
Request changes keeps the draft, gathers the requested correction, supersedes the old proposal/presentation, and shows a complete new preview. An old approval button cannot approve the revision.
-
Approve todo uses Add transactional approval and durable execution recovery #124's atomic claim and returns
execution_pending. No task is written in the Telegram webhook/model request. -
The Add transactional approval and durable execution recovery #124 worker invokes only the todo writer. On success, the bot reports one created todo with its task ID, normalized description, and exact date. Duplicate taps/deliveries return the stored result.
-
A proved pre-write failure says no todo was created and allows a fresh proposal. An uncertain internal write is reconciled by deterministic task identity/strong lookup and never creates a second task.
Ordinary conversation remains the interface. A detached “yes”, a new message after proposal expiry, a group message, or an unconfirmed voice/photo derivation is not approval.
Todo plugin
Register one trusted static plugin in #125's registry:
id: todo
action: propose_create
effect: proposal
core permission: todo:create:self
delivery/recovery: deterministic idempotent create
allowed roles: admin, operator
allowed channel: telegram_private
The production action schema uses additionalProperties: false and accepts exactly description and date. Timezone, actor/assignee, status, source, proposal identity, and execution identity come from trusted core state rather than model input.
The validator must:
- normalize description to Unicode NFKC, trim it, collapse ordinary whitespace, and reject control/zero-width characters, empty content, or more than 500 characters;
- accept only a real Gregorian
YYYY-MM-DDdate, not a timestamp or free-form date; - reject any extra field, multiple todo, list/array, alternate assignee/owner, status, time/reminder, recurrence, or embedded mutation instruction;
- return typed missing/ambiguous-field results rather than guessing;
- treat model/plugin text as untrusted and never interpret description text as instructions;
- produce a pure candidate only; it cannot call task storage or Add transactional approval and durable execution recovery #124 approval/execution methods.
The immutable ProposalSpec binds:
plugin=todo, exact build/schema/policy digests, andaction=propose_create;operation=create,effect=task.create, and destinationdataops.tasks;- normalized description and exact date;
- fixed
status=todo,source=conversational-agent,timeZone=Europe/Berlin; - authenticated actor/owner/assignee DataOps user ID;
- conversation/draft references, permission
todo:create:self, and expiry; - no existing target/base revision, because this is create-only.
The deterministic renderer displays every operator-relevant field listed in the journey. The executor receives only the stored approved spec; it cannot add fields or reinterpret the description.
Clarification, revision, and cancellation
- Missing description: ask what task should be created.
- Missing date: ask for the date.
- Relative date that has one answer from the supplied Berlin current date: convert it and show the exact result in preview.
- Ambiguous date, locale, or reference such as “then”, “next time”, or an unresolved “that”: ask one concise question; do not search broad history or invent context.
- Specific time/reminder request: state that this version stores a date only and ask whether to continue for the exact displayed date.
- Multiple requested tasks: explain that one proposal creates one todo and ask which single todo to prepare first. Do not silently choose or create a batch.
- Request changes: update the
PluginDraftat its expected revision, create a new immutable proposal version, and revoke/supersede every old presentation. - Cancel proposal: revoke approval controls but keep the draft/conversation according to core semantics.
- Discard draft: abandon it according to core semantics.
- Expired proposal: explain that approval expired and regenerate a current preview before presenting a fresh control.
No clarification, model retry, revision, cancel, discard, expiry, or session action calls the writer.
Capability-limited actor-owned task writer
Add a typed ActorTodoWriter separate from generic task CRUD. It accepts only a trusted execution envelope from #124 plus the stored todo spec:
attempt ID and current lease generation
proposal ID/version and canonical payload hash
actor/owner DataOps user ID
description
date
It derives a stable task ID and idempotency identity from the execution attempt/proposal, not from random UUIDs or Telegram deliveries. It writes exactly:
id
description
date
status=todo
source=conversational-agent
assigneeId=actor user ID
createdBy=actor user ID
createdAt / updatedAt
assistantExecutionRef:
executionAttemptId
proposalId / proposalVersion
canonicalPayloadHash
The provenance is safe metadata: no conversation text, Telegram IDs, action tokens, model output, prompt, or secret.
Use one DynamoDB transaction for the internal effect:
- condition-check that the referenced Add transactional approval and durable execution recovery #124 attempt is still
executing, belongs to this exact proposal/actor, has this payload hash, and is owned by the supplied unexpired lease generation; - put the deterministic task only if its key does not exist.
On a conditional collision, strongly read the deterministic task:
- if actor, proposal, attempt, payload hash, description, and date all match, return the same successful safe receipt;
- if any value differs, return a redacted
failed_safeidempotency conflict and never overwrite the task.
The writer exposes no update/delete/list/arbitrary-put capability. The execution worker role receives only the additional task-table GetItem, conditional PutItem, and transaction permissions required by this contract. It receives no task update/delete/scan/query permission.
The safe result receipt contains task ID, actor ID, proposal/attempt references, canonical payload hash, and timestamps. It contains no callback token, prompt/model body, Telegram identifier, or private conversation body.
Extend the Task contract and portable task export/validation/restore only as needed for createdBy and the bounded assistantExecutionRef. Existing task rows without these optional fields remain valid. Export validation rejects malformed or secret-bearing provenance.
Authorization and conflict behavior
The plugin is visible/invocable only for an active linked admin or operator in a private Telegram channel with todo:create:self.
Authorization is rechecked by #125 before invocation, by #124 at approval, and by #124 immediately before the todo writer. The writer additionally binds the attempt/proposal actor to the task owner/assignee in its transaction.
These cases execute nothing:
- unlinked, revoked, disabled, wrong-role, wrong-channel, or group actor;
- another actor's presentation or attempt;
- stale conversation/plugin/draft revision;
- expired/revoked/consumed/superseded presentation;
- changed plugin/build/schema/policy/payload/rendered-view digest;
- detached text such as “yes” without the exact core approval action;
- missing/ambiguous/invalid description or date;
- more than one todo or any unsupported field;
- stale/expired worker lease or mismatched execution envelope.
Create-only todo has no mutable canonical target/base revision. Its conflicts are proposal revision/build/policy/hash drift and deterministic task-ID collisions. A conflict never overwrites an existing task; the user must generate and approve a current proposal.
Failure, recovery, and rollback semantics
- Before approval: there is no task to roll back.
- Approval transaction failure: no attempt and no task.
- Failure before the task transaction: record/prove
failed_safe; no task. - Failure of the task transaction: no partial task because DynamoDB transactions are atomic.
- Crash or lost response after the task transaction commits: keep the task; Add transactional approval and durable execution recovery #124 recovery uses the same attempt/key, reads the deterministic task, and records success without another effect.
- Crash before Add transactional approval and durable execution recovery #124 records the successful receipt: the same recovery behavior applies.
- Stale worker result: cannot overwrite the attempt or task because both the task transaction and attempt finalization check the lease generation.
- Cancel/request changes after approval cannot promise rollback once execution is pending/executing. The bot explains that submitted execution cannot be canceled. This issue adds no task deletion/undo.
No automatic rollback deletes a created task. If a later operator wants deletion or update, they use existing authorized task workflows outside this plugin; adding conversational update/delete is a separate issue.
Acceptance criteria
- The production static registry contains one
todoplugin with onlypropose_create,todo:create:self, private Telegram role/channel restrictions, and a strict two-field schema. - An ordinary private-chat request and confirmed media-derived text use the two-turn Build the static plugin runtime and z.ai conversational adapter #125 path; no task is created during selection, clarification, draft, preview, revision, or approval request handling.
- Missing/ambiguous description/date, specific time, and multiple-task requests receive concise clarification without guessing or batching.
- Relative dates use the supplied current
Europe/Berlindate and the preview always displays an exactYYYY-MM-DD, timezone, and “date only” semantics. - Preview displays the complete normalized description, date, assignee, and status bound to the immutable proposal hashes.
- Request changes supersedes the old proposal/presentations and shows a full revised preview; stale controls execute nothing.
- Core approve/cancel/discard/expiry semantics are reused unchanged; plugins cannot approve themselves or define transitions.
- Approval returns
execution_pending, and only the durable Add transactional approval and durable execution recovery #124 worker can invoke the todo writer. - The writer accepts only the capability-limited schema, rechecks the current attempt lease/proposal/actor transactionally, assigns the task to the actor, and cannot update/delete/query arbitrary tasks.
- One approved proposal creates at most one task with exact approved description/date and fixed status/source/ownership/provenance fields.
- Duplicate callback, update, Stream delivery, worker lease, timeout, and recovery return the same task/result and cannot create another task.
- Wrong actor/channel, revoked permission, stale revision/build/hash/lease, unsupported fields, and deterministic ID collision create no task and overwrite nothing.
- Failure before/inside the write leaves no task; a post-commit lost response preserves and reconciles the one task rather than deleting/recreating it.
-
/todonever invokes the model, plugin, approval flow, or task writer and returns only static conversational guidance. - The current Telegram direct-task compatibility route no longer creates a task from an ordinary message before approval.
- Existing generic task API, task records without assistant provenance, exports/restores, and unrelated assistant/Telegram behavior remain compatible.
- Audit/status/result data is bounded and redacted; it contains no token, prompt/completion, Telegram identifier, secret, or raw conversation body.
- SAM grants the execution worker only the minimal additional task-table permissions and does not grant task mutation to the model/runtime or Telegram webhook path.
- [HUMAN, delegated to Roll out and cut over the Telegram conversational MVP #128 Text + todo] After the Replace the transitional Tasks table with the final cardId schema #166/Gate canonical Card lifecycle on the empty production Cards table #182 sequence and a fresh ordinary all-off deployment, one linked operator sends an ordinary private Telegram todo request, answers one clarification, requests one revision, approves the exact preview, and confirms exactly one canonical matching Task exists. Repeated approval/delivery produces no second Task, while
/todoinvokes no provider/writer and produces no Task. Sanitized evidence is cross-posted here.
Test scenarios
Ordinary conversation and clarification
Given an active linked private user, fake z.ai responses, and requests with complete, missing, ambiguous, relative-date, exact-time, and multi-todo content
When #121 and #125 process each input
Then complete single input reaches one preview, missing/ambiguous values ask one question, relative dates show an exact Berlin date, time requests require date-only confirmation, multi-todo requests select none, and the task writer call count is zero.
Strict plugin schema
Given descriptions with whitespace/Unicode/control/zero-width/oversize variants, valid/invalid dates, arrays, extra fields, alternate assignees/statuses, and embedded instruction-like text
When propose_create validates them
Then only one normalized description plus real date is accepted, instruction-like description remains inert data, unsupported fields are rejected, and no invalid proposal/writer call exists.
Exact preview and revision
Given proposal v1 and revisions changing description or date
When previews are rendered and old/new controls are used
Then each preview/hash contains all current fields, v1 is superseded/revoked, v1 approval creates nothing, and only exact approval of the current version may queue one attempt.
Approval and actor isolation
Given active, disabled, revoked, unlinked, other-user, group, stale-plugin, expired, canceled, and detached-“yes” cases
When invocation or approval is attempted
Then only the exact active actor/private-channel/current-presentation path queues execution; every other case creates no attempt/task and reveals no other user's state.
Capability and field confinement
Given a malicious model/plugin candidate and direct writer calls containing owner/status/bundle/recurrence/time/link/update/delete/arbitrary fields
When validation and execution run
Then every extra capability is rejected, the writer exposes no generic task client, and a valid result contains only the fixed actor-owned todo fields and safe provenance.
Concurrent approval and execution
Given 25 simultaneous approval callbacks, duplicate Telegram updates/Stream records, and concurrent workers
When the full flow runs against DynamoDB Local
Then one proposal/attempt/task ID wins, one task row exists, all idempotent success paths report that same task, and the task contents equal the approved preview.
Conflict and authorization revocation
Given proposal revision/build/schema/policy/hash changes, deterministic task-ID collision with different data, identity disablement, permission revocation, and a stale worker lease
When approval/recovery runs
Then no mismatched task is created or overwritten, no stale worker dispatch succeeds, and the attempt records a safe conflict/failure requiring a fresh proposal where appropriate.
Crash and rollback boundaries
Given injected failure (a) before approval commit, (b) after approval before lease, (c) before task transaction, (d) during transaction, (e) after task commit before return, and (f) after return before attempt-result write
When #124 recovery runs
Then (a,c,d) leave no task, (b) eventually executes, and (e,f) find the exact existing deterministic task and finalize once without delete/recreate/duplicate.
Command and legacy bypass regression
Given /todo, /todo buy milk tomorrow, and the legacy ordinary direct-task input
When the Telegram route processes them
Then commands return static guidance with zero model/writer calls, ordinary input enters conversation/preview, and no compatibility path creates a task before approval.
Export, restore, and redaction
Given ordinary tasks plus conversational todo tasks and malformed/secret-bearing assistant provenance
When portable export validation, dry-run import, and restore tests run
Then optional safe provenance round-trips, legacy tasks remain valid, unsafe provenance fails without echoing the value, and restored records cannot replay an approval.
Infrastructure permissions
Given the SAM template and deployed-role assertions
When validation runs
Then only the execution worker gains the required task GetItem/conditional PutItem/transaction access, while the model/runtime and Telegram webhook paths cannot write tasks directly through this plugin.
Required verification
Software Engineer and Tester must run:
npm --prefix backend test
npm --prefix backend run typecheck
npm --prefix backend run build
make sam-validate
make sam-buildAlso run focused DynamoDB Local tests for plugin validation, actor isolation, 25-way approval concurrency, deterministic task collisions, lease enforcement, all crash boundaries, legacy bypass removal, and portable export/restore provenance. Use injected clocks/current Berlin date, fake z.ai, fake Telegram transport, and no external network or real provider write.
Run the existing Telegram, task API/data-layer, conversational runtime, approval/worker/recovery, portable export, restore, and SAM/IAM test suites in full. Assistant Engineer reviews the plugin/executor boundary before Tester acceptance.
No portal UI changes are in scope, so Playwright/screenshots are not required unless implementation unexpectedly changes a web surface; Tester must explain any omission. The real Telegram/task creation is only the single [HUMAN] sandbox gate above. When all automated work passes first, ship with Refs #126, add human, and leave the issue open until that gate is complete.
Dependencies
- Consolidate private Telegram identity, text, voice, and photo input #121 supplies linked private Telegram identity, ordinary text/confirmed media event normalization, conversations, callback/status rendering, and group fail-closed behavior. Preserve this dependency ID even while its grooming is underway.
- Add transactional approval and durable execution recovery #124 supplies exact proposal rendering/presentations, atomic approval, execution attempts, durable worker leasing/recovery, status events, and capability-scoped executor invocation.
- Build the static plugin runtime and z.ai conversational adapter #125 supplies static registry,
todo:create:self, strict two-turn loading/invocation, context/current-date input, z.ai model adapter, and stale-turn validation. - Define conversational state, proposal records, retention, and recovery #123 is transitively required through all three dependencies for persistent records and DynamoDB access patterns.
Implementation must not weaken a dependency contract. If #121's final interface names differ, adapt this slice to its normalized private-message/action contracts without adding a second Telegram path.
Out of scope
/todomutation shortcut, slash-command parsing into a proposal, or command-based approval.- More than one todo per proposal, batches, partial success, bulk import, or multi-effect plans.
- Task update, delete, complete, waiting/follow-up, undo, recurrence, reminder times/notifications, another assignee, bundle/template linkage, tags, files, docs, proof, or arbitrary task fields.
- Group conversations/topics, web conversation/approval, cross-channel continuation, or notification delivery beyond Consolidate private Telegram identity, text, voice, and photo input #121's Telegram result.
- New voice/photo processing; Consolidate private Telegram identity, text, voice, and photo input #121 owns media conversion/confirmation and this issue consumes only confirmed derived text.
- Typefully, SOP, podcast, GitHub, workflow, calendar, email, or other plugins/effects.
- Personal memory, broad history/reference search, source-document retrieval, or private knowledge ingestion.
- Changes to generic task product behavior beyond optional safe provenance compatibility and the dedicated internal todo writer.
- Retrofitting legacy
AssistantJobapprovals. - Modifying
../dtc-operations,../datatasks, or../podcast-assistant.
Activity
alexeygrigorev commentedon Jul 29, 2026
GROOMED
This issue is implementation-ready after #121, #124, and #125 close.
Key product decisions:
alexeygrigorev commentedon Jul 30, 2026
Software Engineer handoff
Implemented the approved conversational todo creation slice without committing or pushing.
What changed
todo.propose_createplugin with the strict two-field candidate, Berlin date-only policy, static/todoguidance, and no direct effect.ActorTodoWriter/executor. It derives a deterministic task ID and uses one DynamoDB transaction to condition-check the live attempt lease/proposal/actor/hash and conditionally create the fixed actor-owned task.Primary files:
backend/src/conversation/{todoPlugin,proposalCoordinator,todoCore,todoWriter,resultDispatcher}.tsbackend/src/conversation/{execution,executionDefaults,executionRepository,executionWorker,plugins,portable,repository,runtime,telegramAdapter,types}.tsbackend/src/result-notification-handler.tsbackend/src/routes/{telegram,conversationalExecution}.tsbackend/src/{execution-worker-handler,types}.tsbackend/src/export/portable.tsbackend/tests/{todo-conversational,conversational-runtime,telegram-conversational,telegram,export-portable}.test.tsbackend/scripts/test-todo-transaction.shinfra/template.full.yaml,tests/infra/test_template.py,Makefile,backend/README.md,backend/package.jsonVerification
npm --prefix backend test— PASS: 1,313 passed, 0 failed, 1 intentional Docker-only skip (1,314 total).npm --prefix backend run typecheck— PASS.npm --prefix backend run build— PASS.npm --prefix backend run test:todo-transaction— PASS: 6/6 against genuine DynamoDB Local, including 25 concurrent writer deliveries, 25 approvals/workers, deterministic collision/lost-response recovery, atomic outbox, owner isolation, duplicate delivery, ambiguous send, post-claim crash, and retention.npm --prefix backend run test:execution-transaction— PASS: 1/1 against genuine DynamoDB Local with 25 concurrent approvals.npm --prefix backend run test:telegram-transaction— PASS: 3/3 against genuine DynamoDB Local..venv/bin/python -m pytest tests/infra/test_template.py -q— PASS: 25/25.make sam-validate— PASS.make sam-build— PASS; all three functions packaged successfully.git diff --check— PASS.No portal UI changed, so Playwright/screenshots are not applicable. No provider/network mutation or real Telegram message was sent.
Acceptance status
All automatable acceptance criteria are implemented and covered by the full/focused suites above. The remaining
[HUMAN]sandbox Telegram/task-creation gate is intentionally pending; the issue must remain open and the eventual commit should useRefs #126.READY FOR ASSISTANT ENGINEER AND TESTER REVIEW.
alexeygrigorev commentedon Jul 30, 2026
ASSISTANT ENGINEER — CHANGES REQUESTED
The narrow writer/idempotency design is good, the generic coordinator seam is reusable for #127, and the production-style DynamoDB Local flow passes. I cannot pass the boundary yet because the following safety contracts are not implemented end to end.
1. Time/date-only confirmation and multi-todo rejection are model instructions, not trusted state
todoPlugin.tsvalidates only the two returned fields. It accepts, for example,{description: "Call Jane at 09:00", date: "2026-08-04"}and also accepts a description containing multiple requested actions. The only protection is prose inskillInstructions. The validator cannot know that the model silently dropped a requested time/reminder or selected one item from a multi-todo source message.This does not meet the issue's deterministic requirements that a specific time requires explicit date-only confirmation and that multiple requested todos select none. Bind those decisions in core-owned draft state (or another trusted, typed confirmation mechanism) and make proposal creation fail closed unless the stored source/request state proves one task and, where applicable, an explicit date-only confirmation. Add incorrect/malicious fake-z.ai cases that attempt to omit the time or collapse a batch.
2. Permission visibility and revocation are not exact enough
todoto every admin/operator Telegram catalog.ConversationalProposalCoredoes not compute a permission-scopedavailablePluginIdslist in its default path, so an actor lackingtodo:create:selfsees/loads the skill and reaches the model before the invocation-time permission rejection. The issue says the plugin is visible and invocable only with that permission.getApprovalPermission,getIdentityBinding, andgetChannelBindinguse eventually consistent reads. No permission revision is stored in the draft/proposal/attempt.preDispatchCheckand beforeActorTodoWriter.write; the task still commits. The approval transaction is atomic, but it cannot protect a revocation that occurs after approval and before execution.Make visibility permission-scoped before the first model turn. Bind the authorization revision(s) needed by the proposal/attempt, use strong reads where "current" is required, and include current user/permission/identity/channel conditions in the effect transaction (or an equivalent atomic authorization epoch condition) so a revocation cannot race the task write. Add a genuine DynamoDB race test that revokes between preflight and the task transaction.
3. Async result delivery does not revalidate the exact owner binding or enabled user
The notification stores only actor, channel, conversation, and
channelConversationKey; it omits the attempt'sidentityChannelUserId,identityBindingId, andchannelBindingId/revisions. The dispatcher then calls:This assumes a Telegram chat ID is the identity's user ID instead of checking the stored identity key. It also never loads the DataOps user, so a disabled user can still receive a private result. The dispatcher IAM has no Users-table read permission, which confirms that check cannot happen in production. A replaced/rebound binding is accepted as long as actor/conversation happen to match; exact binding revision is not checked.
Persist safe binding references from the approved attempt, then immediately before send strongly revalidate the enabled DataOps user, exact active identity binding, exact private channel binding, actor, and conversation. Keep the executor free of the Telegram secret. Add disabled-user, revoked/replaced identity, replaced channel binding, and chat-ID-vs-user-ID tests. Also pass Telegram
chat_idas the validated string rather than converting the accepted 20-digit value throughNumber, which can lose precision and address the wrong destination.4. Capability rollout is not independently default-off
todoPluginDefinition.enabledis hard-codedtrue,defaultExecutionRegistryalways registersActorTodoExecutor, and the result dispatcher schedule is always enabled. The global conversational Telegram flag protects the webhook, but there is no plugin/executor/result-delivery flag or managed plugin configuration as required by the architecture's enable/disable contract. Add exact default-false rollout controls used consistently by catalog visibility, proposal creation, executor registration/recovery, and result dispatch. Ensure existing claimed attempts have an explicit safe deployment policy rather than becoming executable through a newly registered capability accidentally.5. Missing composed media acceptance proof
The existing Telegram tests prove voice/photo confirmation with a fake core, and the todo test proves the two-turn flow by calling the todo core directly with text. There is no composed test proving confirmed voice- or photo-derived text enters the real two-turn todo proposal path while unconfirmed/canceled media cannot create a proposal/task. Add at least one confirmed photo and one confirmed voice journey through the production adapter/core composition, including stale/cross-actor controls and writer count zero before approval.
Verification performed
npm --prefix backend run test:todo-transaction— PASS, 6/6, including the DynamoDB Local 25-way approval/worker flow and production atomic outbox branch.npm --prefix backend test ...— PASS, 1,313 passed / 1 intentional Docker-only skip. (The package script ran the full suite.)npm --prefix backend run typecheck— PASS.make sam-validate— PASS.No implementation files were changed, committed, or pushed during this review.
alexeygrigorev commentedon Jul 30, 2026
Software Engineer revision handoff
Addressed every blocker from the Assistant Engineer review. No commit or push was made.
Review blockers resolved
Trusted time and multi-todo decisions
confirm date onlyresponse against current core-owned draft state.Permission visibility and revocation safety
Exact private result ownership
chat_idremains a validated string, including 20-digit IDs.Independent default-off rollout
Composed voice and image proof
Verification
npm --prefix backend run typecheck— PASS.npm --prefix backend run test:todo-transaction— PASS: 9/9 against genuine DynamoDB Local, including composed voice/image, 25-way approval/writer concurrency, revocation race, collision, recovery, and result delivery.npm --prefix backend test— PASS: 1,315 passed, 0 failed, 1 intentional Docker-only skip (1,316 total).npm --prefix backend run test:execution-transaction— PASS: 1/1 against genuine DynamoDB Local.npm --prefix backend run test:telegram-transaction— PASS: 3/3 against genuine DynamoDB Local.uv run --with pytest python -m pytest -q tests/infra— PASS: 27/27.npm --prefix backend run build— PASS.make sam-validate— PASS.make sam-build— PASS; all three Lambda functions packaged.git diff --check— PASS.No web UI changed, so Playwright/screenshots are not applicable. No real provider, Telegram, task, deployment, commit, or push mutation was performed. The remaining
[HUMAN]sandbox Telegram gate stays pending, so the eventual commit must useRefs #126.READY FOR ASSISTANT ENGINEER RE-REVIEW AND TESTER.
alexeygrigorev commentedon Jul 30, 2026
ASSISTANT ENGINEER RE-REVIEW — CHANGES REQUESTED
The revision materially closes the five original safety findings:
One architecture blocker and one required proof gap remain.
1. The generic coordinator stops working as soon as a second plugin is enabled
ConversationalProposalCore.handleinitializessourceAdapter/sourceProofonly inside:After the model selects and invokes a plugin, the core unconditionally requires:
Therefore, when #127 enables both
todoandtypefully, the compact catalog can contain both and the model can select one, but every proposal is rejected becausesourceAdapterstayed null. A request-levelcontextProvider.availablePluginIdsfilter does not repair this: source preflight runs before that filter and still sees the full enabled adapter list.Move plugin-specific source preflight to a point where the selected plugin is known while preserving the required pre-model/candidate safety boundary—for example, a bounded core selection/preflight phase between
skill_loadandskill_invoke, or another generic coordinator hook that cannot be bypassed by model candidate output. Add a test with two enabled proposal adapters proving each can be selected, preflighted, proposed, revised, and approved without todo-specific branching in the core. This is the required #127 reusable seam, not a future enhancement.2. The composed image journey stops at preview
todo-media-composed.test.tstakes voice through approval, worker execution, private outbox, and dispatch. The photo branch confirms derived text and reaches a real preview with zero pre-approval writes, but it never approves that preview or verifies worker/task/private-result delivery. The requested re-review gate explicitly includes voice and photo through approval/worker/private result. Complete the photo branch through the same durable boundary and assert one exact task/result, duplicate/stale approval safety, and no media bytes/Telegram identifiers in task provenance or safe receipt.Verification performed
npm --prefix backend run typecheck— PASS.npm --prefix backend run test:todo-transaction— PASS, 9/9 against genuine DynamoDB Local.uv run --with pytest python -m pytest -q tests/infra— PASS, 27/27.make sam-validate— PASS.npm --prefix backend run build— PASS.git diff --check— PASS.No implementation files were edited, committed, or pushed during this review.
10 remaining items
Add conversational todo execution
alexeygrigorev commentedon Jul 30, 2026
Software Engineer handoff — native SAM transform portability regression fixed
Fixed the repository-owned failure in Validate Planning Docs run
https://github.com/DataTalksClub/dataops/actions/runs/30532699890 on pushed
mainc47c5258a08b29c7c5ea6e797149c8a6619bbe71. The change is isolated inbranch
hotfix-126-sam-portability, remains intentionally uncommitted andunpushed, and is ready for independent Tester review.
Root cause and fix
tests/infra/test_template.pytreatedshutil.which("sam")as UTF-8 source andused its first line as a Python interpreter. That worked for pip/uv SAM wrappers
but setup-sam's recommended native installer provides an ELF executable, so CI
failed with
UnicodeDecodeErrorbefore any transform.The test now:
native executable directly;
validate --debugtransform twice, oncewith the production default-off template and once with an isolated
explicit-true parameter-default variant under the repository-local
.tmp/;AWS::Events::Rule, the exactFn::If [ConversationalResultDeliveryIsEnabled, ENABLED, DISABLED]state,the exact equality condition, and the transformed
false/truedefaults;script and the native Python ELF used by the test process.
There is no binary-path skip and no replacement with a static-only assertion.
Changed file
tests/infra/test_template.pyTracked diff fingerprint:
9ccfc0fa59b0253419c22a4728e38115c6fb80396d23707a4e88469a92313f78Verification
PASS, 3/3.
PATH=<native-sam-dist> uv run --with pytest python -m pytest tests/infra—PASS, 35/35.
make validate-planning-docs— PASS, 7/7.make sam-validatewith empty local AWS config/credentials —PASS.
sam validate --template-file infra/template.full.yaml --lintwithempty local AWS config/credentials — PASS.
make sam-build— PASS; all six functions packaged.npm --prefix backend testafter the required cleannpm ciin the isolatedworktree — PASS, 1,375 passed, 1 intentional transaction-harness skip,
0 failed.
npm --prefix backend run typecheck— PASS.git diff --check, single-file scope, conflict/credential-pattern scan —PASS.
The first proportional backend run before
npm cireported only a missinglocal
@aws-sdk/client-sesv2package; installing the locked dependencies andrerunning the complete suite produced the clean result above. No product file
was changed for that environment setup.
No portal/frontend behavior changed, so screenshots and Playwright are not
applicable. No commit, push, deploy, AWS mutation, provider call, or Telegram
message was performed. Existing #126 HUMAN gates remain unchanged; an eventual
commit must continue to use
Refs #126and leave the issue open.alexeygrigorev commentedon Jul 30, 2026
On-Call report — main
c47c525(Refs #126)Both workflows triggered for
c47c5258a08b29c7c5ea6e797149c8a6619bbe71reached terminal failure, for two independent and precisely classified reasons. No manual deploy, AWS mutation, provider call, or Telegram action was performed by On-Call.1. Repository/application checks and packaging
Deploy DataOps V1 Lambda run 30532699861 completed its
Check DataOps v1 appjob successfully in 5m18s:The successful check build packaged exactly the relevant six functions, including:
ConversationalExecutionWorkerFunction;ConversationalResultDispatcherFunction;SponsorSendWorkerFunction;SponsorSesEventFunction;SponsorPrivateArchiveFunction;BackendFunction.The deploy job independently rebuilt the same six functions and ended with
Build Succeededbefore calling CloudFormation. This is direct CI evidence that the new worker and dispatcher compile and package on the GitHub runner.The ordinary backend CI command deliberately skips the Docker/DynamoDB Local transaction harness; this run therefore is not new CI execution evidence for those dedicated suites. The accepted current-tree Tester evidence remains: todo 10/10, execution 1/1, Telegram 4/4, sponsor finance 16/16, and sponsor communications 19/19: #126 (comment). Adding the dedicated transaction commands to CI is a separate coverage decision; this report does not misrepresent the one skipped test as executed in Actions.
2. Code/test portability regression in the second workflow
Validate Planning Docs run 30532699890 failed before any AWS operation. SOP lint and planning-doc validation passed, but
tests/infrafinished 32 passed, 1 failed.The failing #126 transform test at
tests/infra/test_template.py:202callsPath(shutil.which("sam")).read_text(...)to extract a Python shebang.aws-actions/setup-sam@v3installs a native ELFsambinary in CI, so the read raisesUnicodeDecodeErrorbefore the transform assertion runs. This is a repository-owned portability defect, not IAM, AWS, z.ai, Telegram, or a flaky assertion. It must be corrected by Software Engineer and re-run; On-Call did not edit or push feature code.3. AWS deployment and terminal rollback
The deploy job successfully configured OIDC credentials, passed its second SAM build, and invoked the normal
sam deploypath with all three #126 rollout flags resolving tofalse:ConversationalTodoPluginEnabled=false;ConversationalTodoExecutorEnabled=false;ConversationalResultDeliveryEnabled=false.CloudFormation then received the same live-role denials already covered by accepted but unapplied
DataTalksClub/aws-infrasource at2a1b95f:sqs:CreateQueuedenied forConversationalExecutionFailureQueue(Add transactional approval and durable execution recovery #124);sqs:CreateQueuedenied forSponsorCommunicationFailureQueue(Repair DataOps OIDC SES configuration-set tag-on-create permission #129);ses:CreateConfigurationSetdenied forSponsorSesConfigurationSet(Repair DataOps OIDC SES configuration-set tag-on-create permission #129).The dispatcher role reached
CREATE_IN_PROGRESS, then was cancelled by the primary failures and deleted during rollback. The dispatcher function, schedule, and live default-disabled state were therefore not created or verified. No separate dispatcher-policy denial was reached, so this run is not direct live #130 acceptance evidence.The stack ended cleanly at terminal
UPDATE_ROLLBACK_COMPLETE. Runtime seeding and deployed-backend smoke tests were skipped. This is an external live-IAM prerequisite failure, not an application build/package regression.Required next actions
Refs #126follow-up.dataops-github-actionsstack fromDataTalksClub/aws-infra2a1b95fwithCAPABILITY_NAMED_IAM, and verifies the effective Add transactional approval and durable execution recovery #124/Repair DataOps OIDC SES configuration-set tag-on-create permission #129/Repair dispatcher generated-role IAM prefix for CloudFormation rollback #130 attachments. Do not replace normal DataOps CI/CD with a manual app deployment.mainpush. Require both workflows green, the default-off deployment successful, and On-Call inspection of the dispatcher function/role/log graph plus disabled result-delivery rule.#126 remains open with the
humanlabel. The issue must not close until the external apply/deploy and live Telegram criteria pass.alexeygrigorev commentedon Jul 30, 2026
TEST PASS — native SAM portability hotfix fixes run 30532699890 without weakening the transform contract
I independently reviewed and tested the uncommitted one-file hotfix in
hotfix-126-sam-portability. I did not edit product/test source, commit, push, deploy, call AWS/Telegram/z.ai, or perform PM acceptance.Reviewed state and root cause
c47c5258a08b29c7c5ea6e797149c8a6619bbe71.tests/infra/test_template.py.9ccfc0fa59b0253419c22a4728e38115c6fb80396d23707a4e88469a92313f78.\x7fELF...executable as UTF-8 and raisedUnicodeDecodeErrorbefore invoking SAM. The other 32 tests passed.Hotfix contract
_executable_commandreads only the first line as bytes, directly returns native executables, and replays a UTF-8 shebang as an argv list. There is noshell=True, shell interpolation, orshlexevaluation. A Python shebang with its single optional interpreter argument executes correctly; a native ELF executes directly.$(...); argv remained literal and no sentinel file was created. Invalid UTF-8 shebangs fail with an assertion.validate --debugtransform for two project-local.tmptemplate variants. It does not import SAM internals, skip binary SAM, or replace the transform with a static source check.AWS::Events::Rule, exactFn::If [ConversationalResultDeliveryIsEnabled, ENABLED, DISABLED]state, and exactFn::Equals [Ref ConversationalResultDeliveryEnabled, 'true']condition. The production variant has default'false'; the isolated explicit-on variant has default'true'.check=True, and the true variant can only be produced after the expected productionDefault: "false"block is found and changed in the scratch copy.SAM_CLI_TELEMETRY=0, disable EC2 metadata, and point AWS config/credentials at empty scratch paths.Commands and results
uv run --with pytest python -m pytest -vv tests/infra/test_template.py -k 'conversational_result_delivery_schedule or sam_executable_command'with the local pip/uv shebang SAM — PASS, 3/3 selected.aws/aws-sam-clireleasev1.164.0;file dist/dist/samproves an x86-64 ELF andsam --versionreports 1.164.0.PATH— PASS, 3/3 selected.PATH=<native-sam-dist> uv run --with pytest python -m pytest -q tests/infra— PASS, 35/35.ARGV_SECURITY_AND_FAIL_CLOSED: PASS).make validate-planning-docs— PASS, 7/7.PATH=<native-sam-dist> ... make sam-validatewith empty AWS config/credentials and metadata/telemetry disabled — PASS.PATH=<native-sam-dist> ... sam validate --template-file infra/template.full.yaml --lint— PASS.PATH=<native-sam-dist> ... make sam-build— PASS; all six functions packaged: conversational execution worker, sponsor send worker, sponsor SES event, sponsor private archive, conversational result dispatcher, and backend.npm --prefix backend test— PASS, 1,375 passed, 1 intentional genuine-transaction harness skip, 0 failed (1,376 total).npm --prefix backend run typecheck— PASS.npm --prefix backend run build— PASS.git diff --check; single-path/base/hash assertions; conflict-marker scan; Telegram token, AWS key, private-key, GitHub-token, and generic credential-pattern scan — PASS.No UI/page behavior changed, so Playwright and screenshots are not applicable. Existing #126 HUMAN gates are unchanged: the credentialed deploy-role stack application and live private Telegram todo journey remain external checks. The eventual commit must continue to use
Refs #126, retainhuman, and leave the issue open.alexeygrigorev commentedon Jul 30, 2026
PM ACCEPTED — native SAM portability hotfix
I accept the frozen one-file hotfix for the Software Engineer commit gate.
c47c5258a08b29c7c5ea6e797149c8a6619bbe71.tests/infra/test_template.py.9ccfc0fa59b0253419c22a4728e38115c6fb80396d23707a4e88469a92313f78.validate --debugtranslation for both the production default-off template and an isolated explicit-true scratch variant; both must contain the generated Events rule, the exactFn::If [ConversationalResultDeliveryIsEnabled, ENABLED, DISABLED]state, and the exact equality condition, with translated defaults proven asfalseandtrue. Missing translation markers/resources/semantics, a non-zero SAM exit, or inability to construct the expected true scratch variant fails the test..tmp, telemetry and metadata lookup are disabled, and no credential/config fixture is inherited for the transform. No product/runtime/UI behavior, deployment configuration, or unrelated file is changed.Shipping instruction: commit this exact tree unchanged with
Refs #126(notCloses #126), retain thehumanlabel, and leave #126 open. After the normal local merge andmainpush, On-Call must monitor fresh CI/CD. The credentialed deploy-role stack apply, successful default-off deployment/runtime inspection, and live Telegram todo journey remain HUMAN gates; this acceptance does not claim them complete.No file, commit, push, deploy, AWS mutation, provider call, or Telegram action was performed during this PM review.
Fix native SAM transform test portability
alexeygrigorev commentedon Jul 30, 2026
On-Call report — SAM portability follow-up
c8d153c(Refs #126)All workflows triggered by pushed main commit
c8d153cf1ddb07acca6846182b4f65af9338b6ffare terminal.Fresh push evidence
Validate Planning Docs run 30533952036 completed success in 35 seconds.
The exact regression path is fixed on the GitHub-hosted runner:
aws-actions/setup-sam@v3used its native installer and restored AWS SAM CLI 1.164.0;uv run --with pytest python -m pytest tests/infracollected and passed 35/35 tests in 2.93 seconds;tests/infra/test_template.pypassed all 33 of its tests, including the real default-off and explicit-true SAM transform contract;UnicodeDecodeError, ELF decode attempt, skip, or weakened static-only replacement;The only annotation is the non-blocking GitHub Actions Node 20 deprecation warning. It did not affect the run.
Application and deployment classification
This test-only path triggered only Validate Planning Docs; it did not trigger a fresh Deploy DataOps V1 Lambda workflow. Therefore this report does not claim a fresh application build or deployment.
The immediately preceding Deploy run 30532699861 remains the applicable application/package evidence for the unchanged product tree: its Check DataOps v1 app job passed backend 1,375 plus 1 intentional transaction-harness skip, typecheck, build, Playwright 352/352, SAM validation, and SAM build; the deploy job also rebuilt all six functions successfully.
That preceding deploy then ended at terminal
UPDATE_ROLLBACK_COMPLETEonly after the already-classified live-role denials forsqs:CreateQueueandses:CreateConfigurationSet. Accepted permission source exists inDataTalksClub/aws-infraat2a1b95ffor #124/#129/#130, but a credentialed operator has not yet proven the named-IAM stack applied. The dispatcher resource was cancelled during rollback, so there is still no live dispatcher graph or default-disabled rule evidence. No new IAM denial or new live evidence was produced by this test-only push, so no duplicate IAM issue comments were added.Status and handoff
humanlabel.On-Call performed no code edit, commit, push, manual deploy, AWS mutation, provider call, or Telegram action.
alexeygrigorev commentedon Jul 31, 2026
PM STATUS RECONCILIATION — todo code and portability fix complete; live journey pending
c47c5258a08b29c7c5ea6e797149c8a6619bbe71(Refs #126) and portability hotfixc8d153cf1ddb07acca6846182b4f65af9338b6ff(Refs #126) are onmain.main. The former downstream blocker claim is historical: Ship approved Typefully saved-draft creation #127 code shipped and Roll out and cut over the Telegram conversational MVP #128 owns rollout. Ship approved conversational todo creation #126 does not depend on Roll out and cut over the Telegram conversational MVP #128; its remaining normal-deployment gate is Migrate Sponsor CRM GSIs in a protected stage-only workflow #136 → Reconcile missing CloudFormation ownership provenance for Sponsor CRM table #140 → Close out the retained CloudTrail audit session record #141.PM decision: keep #126 open with
human. After normal deployment can proceed,a linked operator must complete the single unchecked Telegram todo journey,
including clarification, revision, exact approval, exactly one matching task,
duplicate-approval idempotency, and
/todoproducing no task. No live Telegram,z.ai, task-creation, or provider success is claimed.
No code, AWS, IAM, workflow, environment, Telegram, z.ai, or other provider
action was performed during this reconciliation.
alexeygrigorev commentedon Jul 31, 2026
PM tracker reconciliation — todo rollout dependency corrected
The accepted implementation remains on
main. Replaced the stale #141 chain with #140 lifecycle acceptance plus #143 ownership remediation, recorded the #128 On-Call→authorized-HUMAN sequence and exact deployment resume signal, and removed the prematurehumanlabel while agent/deploy gates remain. No Telegram action or criterion completion occurred.alexeygrigorev commentedon Aug 13, 2026
PM lifecycle reconciliation — source/default-off complete; HUMAN todo subset stays in #128
The stale #136/#143 dependency has been removed. #126 implementation commit
c47c5258a08b29c7c5ea6e797149c8a6619bbe71and portability follow-upc8d153cf1ddb07acca6846182b4f65af9338b6ffare accepted ancestors oforigin/main; #128 rollout source is integrated, and normal OIDC runs 31545689094 and 31711997388 prove the all-off deploy/seed/smoke path. They do not prove a live Telegram/model/task effect.The Task contract has moved forward safely. Accepted #179 commit
02ee455efad09865ecdbd578e940c59e0bf7dc36adds canonicalversion: 1/taskHistory: []creation, and accepted #168 commit41dca9e3748fe627c195f48a7f97ae203b343f60keeps the todo path inside the strict Task/Card lifecycle and portable contract. Both are exact ancestors of current localmain, but neither is onorigin/mainor active in the sandbox. No compatibility, migration, import, export, or restore path is needed.The remaining closure path is now exact and owned by #128:
/todoinvokes neither provider nor writer and creates nothing.Voice/photo, Typefully, unrelated alarm canaries, and the rest of #128 are not #126 closure requirements. #126 remains open with
human. No repository edit, test, AWS/Telegram/provider call, deployment, credential access, data operation, dispatch, import, export, migration, or restore was performed in this reconciliation.Add conversational todo execution
Fix native SAM transform test portability