Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2f5eee3
test(harness): anchor the credits-expiry case to the real observation…
Sep 25, 2026
31b42fe
fix(im): a running turn's words reach IM and web while it runs (#209)
Sep 25, 2026
9889a51
docs: a running turn's words reach IM and web as it runs (#209)
Sep 25, 2026
615eb01
fix(im): only an open structured turn seals a card mid-turn (#209)
Sep 25, 2026
70b63b1
fix(im): say which answers are interim, and keep a turn's pieces whol…
Sep 25, 2026
5a1aed1
fix(im): a watchdog heads-up and an approval prompt are interim (#209)
Sep 25, 2026
1604125
fix(web): an interim answer is shown live and never ends the turn (#209)
Sep 25, 2026
cf32cbf
fix(web): only an answer marked interim keeps the turn running (#209)
Sep 25, 2026
79d5286
fix(dsh): an interim answer is shown live and never ends the turn (#209)
Sep 25, 2026
aa7a1dc
fix(dsh): only an answer marked interim keeps the turn running (#209)
Sep 25, 2026
b0e2636
fix(im): a turn's answer is delimited by its own rows (#209)
Sep 25, 2026
6541b81
fix(harness): an ACP chunk with no open turn sends no liveness pulse …
Sep 25, 2026
0cabce5
fix(dsh): nothing after a turn's end reopens a phantom working turn (…
Sep 25, 2026
457171c
feat(im): a threaded channel scopes session focus to the thread (#19)
firstintent Oct 3, 2026
772833f
build: bump async-trait to 0.1.92 for rustc 1.99 clippy
firstintent Oct 3, 2026
b99a373
fix(im): /cd in a thread never adopts another thread's session (#19)
firstintent Oct 3, 2026
8f2a261
docs: Slack as an IM, one thread per session (#19)
firstintent Oct 3, 2026
5db1785
feat(im): Slack over Socket Mode, one thread per session (#19)
firstintent Oct 3, 2026
68501f8
feat(cli,web): configure the Slack app from `ccteam config` and the A…
firstintent Oct 3, 2026
77af6b1
feat(web): Slack card in the admin access settings (#19)
firstintent Oct 3, 2026
5facacf
docs: Slack reacts with the ack emoji; enable the app's DM tab (#19)
firstintent Oct 3, 2026
c95fb53
fix(im): a session lives in one thread; moving it tells the thread it…
firstintent Oct 3, 2026
7a80fa1
fix(im): restoring routes keeps one thread per session (#19)
firstintent Oct 3, 2026
431c268
fix(im): pickers are clickable wherever the provider renders buttons …
firstintent Oct 4, 2026
c630849
feat(im): each Slack app answers its own slash command (#19)
firstintent Oct 4, 2026
f033c7d
feat(web): a guided Slack setup card — create, paste tokens, allow yo…
firstintent Oct 4, 2026
13325c0
docs: Slack setup is the web card; one app per ccteam daemon (#19)
firstintent Oct 4, 2026
9f5dbe0
feat(im): on Slack a command starts with `!` (#19)
firstintent Oct 4, 2026
7ed2551
docs: Slack commands start with `!` (#19)
firstintent Oct 4, 2026
dd8f43c
feat(im): tap instead of type — next steps are buttons (#19)
firstintent Oct 4, 2026
6e3a016
docs: Slack is driven by buttons first (#19)
firstintent Oct 4, 2026
74f1191
fix(im): /help is a short grouped list, safe for Slack (#19)
firstintent Oct 4, 2026
97b7178
feat(im): status and model are the big buttons, interrupt the small o…
firstintent Oct 4, 2026
20141cf
fix(im): Slack lists show every label, one button per row (#19)
firstintent Oct 4, 2026
d3a28bf
feat(acl): the owner's IM chats share sessions; a session still pushe…
firstintent Oct 4, 2026
634d3b6
docs: the ACL red line — owner's IM chats share visibility, push stay…
firstintent Oct 4, 2026
c95017d
release: v0.12.0 — Slack, one agent session per thread
firstintent Oct 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ ccteam = 多 harness agent 团队的桥接与治理层:常驻 daemon(IM gateway
| **daemon 无自主内容决策循环** | 只响应消息、排程与连接;引擎不产生任务、不选择工作;编排智能永在会话/用户空间 |
| **`progress.jsonl` 是 state SoT** | schema 权威 = `harness/progress_bridge`,`core` 只 re-export;对话原文 = `<project>/.ccteam/chat/<sid>/turns.jsonl`(按 sid;gateway `spawn_event_pump` 是 live daemon 唯一 turns writer) |
| **session = 独立一等实体** | 持久 `sid`(`s<N>`,单调、扛重启、不复用)是唯一身份,任何属性都不参与去重;turns/marker/pane 全按 sid;生命周期 = spawn-on-demand + resume-by-sid + 空闲释放/容量挤停,非常驻吊着;chat 复用 context 是 feature |
| **ACL = 一个身份解析器 + 一套归属策略,两个前端共用(fail-closed)** | ①身份:`Gateway::principal` 唯一解析器,三态 Operator(admin web token / 全局 bot 允许列表点名的 chat)/ Tenant(`<platform>@<tenant>` bot 或 per-user web token → `user:<tenant>`)/ Guest(进门未点名:只拥有自己建的,看不到任何 project);「够得着 bot」≠「是 operator」,`"*"` 通配点名零人(`bind_operator_allowlist`;空表 = 未配置,单人默认 + 启动告警)。②归属:project 是归属单元(`ProjectState.owner`),session 继承;唯一策略 = `ccteam_core::identity::{can_see_owner, can_see_session_owner}`,IM/web/MCP 全走它;session 可见 = 自己建的 ⊕ 自己身份的 web 控制台池;IM chat 互相隔离,web 不看 IM session;「同-current-project 互看」已反转删除,勿加回。③解析永不越界:`current_project_for` 只在本人可见集里落地(`/cd` 选的 → daemon 默认(可见时)→ 本人首个),无可见项目 = 拒绝并给下一步,绝不回落 daemon 默认项目。④门:REST 单一 choke point = `auth::project_acl_layer`(认全部项目寻址族 `/api/v1/projects/{slug}/*` · `/api/{slug}/*` · `/ws/{slug}/*`,新路由自动覆盖);`/sessions/{sid}/*` 按其 project 门(admin 同样过门);集合面与 SSE 按身份过滤;`/ws/chat` 身份取自认证态不认 query;admin 专属只剩 `/users*` + 全局 `/config/im`(tenant 自助面 = `/me/im`),deny→403;SPA 仅管理员 tab 按 `GET /api/v1/me` 显隐。诚实范围:同 OS uid 下是软隔离(UX)非安全边界;web↔IM 同一人复联 deferred |
| **ACL = 一个身份解析器 + 一套归属策略,两个前端共用(fail-closed)** | ①身份:`Gateway::principal` 唯一解析器,三态 Operator(admin web token / 全局 bot 允许列表点名的 chat)/ Tenant(`<platform>@<tenant>` bot 或 per-user web token → `user:<tenant>`)/ Guest(进门未点名:只拥有自己建的,看不到任何 project);「够得着 bot」≠「是 operator」,`"*"` 通配点名零人(`bind_operator_allowlist`;空表 = 未配置,单人默认 + 启动告警)。②归属:project 是归属单元(`ProjectState.owner`),session 继承;唯一策略 = `ccteam_core::identity::{can_see_owner, can_see_session_owner}`,IM/web/MCP 全走它;session 可见 = 自己建的 ⊕ 自己身份的 web 控制台池 ⊕ owner 的 IM 会话池(owner 2026-10-05:bot 允许列表**点名**的 owner chat 互看全部 IM 会话,开放模式不算,`operator_im_pool_sees`);**可见 ≠ 推送**:会话只推给唯一 reply 目标(最后驱动/显式切过去且仍聚焦的 chat),绝不广播;其余 IM chat 互相隔离,web 不看 IM session;「同-current-project 互看」已反转删除,勿加回。③解析永不越界:`current_project_for` 只在本人可见集里落地(`/cd` 选的 → daemon 默认(可见时)→ 本人首个),无可见项目 = 拒绝并给下一步,绝不回落 daemon 默认项目。④门:REST 单一 choke point = `auth::project_acl_layer`(认全部项目寻址族 `/api/v1/projects/{slug}/*` · `/api/{slug}/*` · `/ws/{slug}/*`,新路由自动覆盖);`/sessions/{sid}/*` 按其 project 门(admin 同样过门);集合面与 SSE 按身份过滤;`/ws/chat` 身份取自认证态不认 query;admin 专属只剩 `/users*` + 全局 `/config/im`(tenant 自助面 = `/me/im`),deny→403;SPA 仅管理员 tab 按 `GET /api/v1/me` 显隐。诚实范围:同 OS uid 下是软隔离(UX)非安全边界;web↔IM 同一人复联 deferred |
| **不解析终端输出** | 读 transcript jsonl + 官方 hooks fast event;不 scrape pane(`tmux capture-pane` 仅 dev 调试;web 终端快照走 pane-snapshot 只读)|
| **terminal 协议(tmux/rmux)冻结 = 维护-only** | 新 vendor / 新功能不得新增 tmux/rmux/PTY 依赖(新 harness 一律长驻 stdio:stream-json / ACP / app-server);既有 Claude `terminal` 只修不扩;逐字节终端镜像不再是新功能验收条件 |
| **永不主动 kill 长 session(kill 的是进程,不是会话)** | 会话 = sid + 账本 + 焦点路由,永不被 daemon 自行终结;daemon 只管常驻(residency):`resident` / `released`(下条消息按 sid 冷 resume)/ `stopped`(用户显式,`meta.stopped_at`)/ `detached`(体外活)。空闲释放 = 主机制(`sessions.idle_release_secs` 默认 3600 = claude prompt-cache TTL;`idle_release_by_vendor.<harness>` 覆盖;0 = 永不;资格 = 无在飞 turn ∧ 无 HITL 等待 ∧ 无 outlives-turn 后台任务);容量挤停 = 次级硬上限(`sessions.max_live`,LRU;等待用户决定的会话与新会话父链绝不挤,创建永不因容量失败);两者同一条释放路(`session_evicted{reason:idle\|capacity}` + lifecycle 广播),都不删焦点路由;daemon 重启不重生进程(只探 body)。预算例外:`budgets.*.max_cost_usd_per_24h` 触顶 auto-disable。`project stop` / `/stop` / `rm --force` 是用户显式命令;`/compact /new` 是合法 turn,`/new` 总铸新 sid |
Expand Down
Loading
Loading