Brainstorm Review · Agentee post-v1.0.0

Dynamic Workflow Platform & Share Proposal/Conversation

Tổng hợp toàn bộ thảo luận ngày 17/06/2026 — đánh giá spec-17-jun + thiết kế feature share proposal kèm hội thoại. Tài liệu review trước khi sang /ck:plan.

📅 2026-06-17 ✅ Consensus reached 🎯 Chờ /ck:plan 🏢 Tenant-internal

1Đánh giá giải pháp Dynamic Workflow (spec-17-jun)

Spec nêu 2 vấn đề: (1) workflow động — quản lý như package, customize qua markdown; (2) generic output + share/merge giữa nhiều người.

Verdict: Hướng đúng chiến lược (workflow hardcode không scale ra nhiều SME). Nhưng spec đọc như một "platform 2.0", không phải iteration — risk lớn nhất là scope explosion + reinvent cái team đã build. Đã chốt 4 fork an toàn bên dưới để kiểm soát.

Quyết định đã chốt (user-confirmed)

#Chủ đềLựa chọn
E1Scope / sequencingPhased: engine → generic output → collab merge. Layer phụ thuộc nhau, không làm song song. Mỗi layer 1 plan riêng.
E2Vai trò MarkdownMarkdown = lớp authoring → LLM compile ra JSON graph; engine execute graph deterministic. Giữ approval gate / branch / state. Refine, không phá quyết định 260610.
E3Merge đa ngườiPartition ownership + suggestion accept/reject (tái dùng đồ đã build). KHÔNG CRDT/Google-Docs (YAGNI, khó audit).
E4Đóng góiInternal module packages/workflow-engine trong monorepo; extract npm chỉ khi có consumer thứ 2 thật.

Roadmap phân lớp

1
EngineResurrect design 260610: schema + JSON-graph interpreter + node executors + markdown→graph compiler + approval queue
on paper
2
Generic outputGeneralize từ proposalState JSONB + proposal_sections → output container validate bằng JSON Schema
semi-ready
3
Collab / mergeGeneralize partition-ownership + suggestion-accept cho mọi workflow output
~80% built
ValidateChứng minh "generic" bằng 1 workflow thật thứ 2 (expense approval / onboarding) trước khi gọi là generic
gate

2Feature: Share Proposal + Conversation

PO tham chiếu "share như Claude/Codex", nhưng mô tả thực tế là live collab trên artifact — không phải snapshot của Claude.

Điểm hay của model: proposal = artifact dùng chung; conversation = per-user thread; transcript của A share read-only cho B. Vì mỗi người có session riêng → agent luôn chạy đúng identity từng người → né được lỗ hổng leo thang quyền (agent-acts-as-whom) khi B làm tiếp.

Kiến trúc: 1 proposal ↔ N session

Session của A
owner = A · agent chạy as A
transcript
read-only
Session của B
owner = B · agent chạy as B
📄 PROPOSAL (state canonical dùng chung)
proposal_workspaces.proposalState + sections · lock_version serialize writes · current_assignee

Quyết định đã chốt (user-confirmed)

#Chủ đềLựa chọn
S1Session ↔ proposalN session/proposal (mỗi user 1). Transcript A share read-only. ⚠️ Reversal đảo thiết kế 260610-1313 (đang 1 shared thread) — user xác nhận chủ động đổi.
S2Quyền xem transcriptTranscript session của sharer thành read-only với recipient; scope theo proposal collaborator, nội bộ tenant. B không bao giờ ghi vào thread của A.
S3Quyền edit khi shareSharer chọn lúc share: handoff (reassign current_assignee→B) HOẶC reviewer (B suggest, A accept/reject).
S4Share cho aiNội bộ tenant (recipient là user có account). Public/external link out-of-scope.
S5ScopeProposal/workflow thread trước. Share general chat_ui để sau.

3Luồng A → B (step-by-step)

Ví dụ: A làm proposal tới bước technical_proposal rồi share cho B.

A = người gửi (sharer) Hệ thống B = người nhận (recipient)
A
Sharer
Xây proposal đến bước technical_proposal
Làm việc với agent trong session riêng của A; proposal state được tích lũy dần.
A
Sharer
Nhấn Share → chọn B + chọn mode
Mode = handoff (giao quyền edit) hoặc reviewer (B chỉ suggest). Kèm theo transcript hội thoại A↔agent.
System
Add B làm collaborator + grant read-only transcript + gửi noti
Role gán theo mode. Reuse: proposal_collaborators, notifications.
B
Recipient
Nhận noti → mở ra
Đọc read-only luồng A đã discuss với agent + xem state proposal hiện tại (getDetail). Hiểu state được build ra sao.
B
Recipient
Nhấn Continue → tạo session riêng của B
Session mới bound vào cùng proposal, owner = B. Agent chạy as B (ERP JWT của B). Đây là chỗ cần relax unique index để cho phép session thứ 2.
Mode: Handoff
B thành current_assignee → edit proposal trực tiếp, serialize bằng lock_version.
Mode: Reviewer
B tạo proposal_suggestions (replace_section / json_patch) → A accept/reject.
System
State proposal (shared) cập nhật
Mọi thay đổi đổ về 1 state canonical. Suggestion có staleness detection (base_section_updated_at) nếu state đã dịch chuyển.

4Built vs New — net-new rất nhỏ

Phần lớn capability đã có sẵn từ các plan trước; chỉ 2 thứ thật sự mới.

✅ Reuse đã build 🆕 New làm mới
CapabilityTrạng tháiNguồn
Add B làm collaborator (role, permission)✅ Reuseproposal_collaborators + collaboration controller
Notify B✅ Reusenotifications + proposal-assignment-notifications
B xem state proposal hiện tại✅ ReusegetDetail (workspace+steps+sections)
Handoff (reassign current_assignee)✅ Reuseproposal-reassign-via-chat · PROPOSAL_ASSIGN_ENABLED
Reviewer (suggest + accept/reject + staleness)✅ Reuseproposal_suggestions
Serialize writes✅ Reuselock_version optimistic lock
B đọc read-only transcript của A (cross-user)🆕 NewHiện sessions.service chặn mọi cross-user read
N session/proposal (mỗi user 1)🆕 NewRelax UNIQUE index uq_chat_sessions_active_proposal_erp

4 hạng mục net-new cần build

  1. Relax unique index → cho phép 1 session / (proposal, user) thay vì / proposal. Migration + cập nhật _journal.json.
  2. Cross-user read-only transcript path trong sessions.service: collaborator được READ (không bao giờ WRITE) messages của session bound-proposal của người khác. Scope tenant + collaborator.
  3. Share gesture/endpoint: gói chung add-collaborator + grant-transcript + notify + mode (handoff|reviewer).
  4. chat-ui: nút Share + picker người nhận + picker mode; view read-only transcript + state + nút "Continue" → spawn session riêng.

5Risks & điểm cần audit

Cần xử lý lúc planning, đặc biệt phần đụng tới code đang chạy.

Top risk
Reversal blast radius
Relax unique index có thể vỡ code giả định "1 session/proposal". Phải audit findOrCreateForChannel + canonical-session binding + mọi reader của activeProposalId TRƯỚC khi migrate.
Read-only bị rò thành write
B đọc transcript A không được phép post vào thread A. Enforce read-only ở service; agent runtime chỉ target session của chính requester; có test.
Agent identity khi continue
Đã giải quyết bằng per-user session (agent chạy as session owner). Giữ invariant này tường minh trong code.
Transcript chứa nội dung nhạy cảm
Share là hành động consent rõ ràng; MVP share toàn bộ transcript (theo mô tả PO "kèm conversation đã thảo luận").
State dịch chuyển khi B review
Reuse suggestion staleness (base_section_updated_at) → đánh dấu stale, không apply mù.
Scope creep sang general chat
Giữ S5: proposal/workflow thread trước. Share chat_ui thường (đắt: rework single-owner stack) để sau.

6Next steps

Feature share này ship ĐỘC LẬP với workflow engine — proposal collab đã tồn tại nên không bị block bởi Layer 1/2/3. Về mặt khái niệm, nó là share/invite gesture mà Layer 3 sau này sẽ generalize cho mọi workflow output.

Khi sẵn sàng, handoff sang plan (nghiêng --tdd vì sửa code critical: access gate + session binding):

/ck:plan --tdd plans/reports/brainstorm-260617-share-proposal-conversation.md

2 brainstorm đang chờ plan: ① Dynamic Workflow Platform (engine-first) · ② Share Proposal + Conversation (feature này, ship sớm được). Cả hai đã có report + memory lock decisions.