Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e97d5b1
feat(project): add role assignment bootstrap
KeepSilenceQP Jul 25, 2026
f18cbc7
docs: specify shared bot registry and named project roles
KeepSilenceQP Jul 26, 2026
f9a3e1e
docs: add shared bot registry and named project roles coding plan
KeepSilenceQP Jul 26, 2026
f84f2c4
docs: revise shared bot registry coding plan
KeepSilenceQP Jul 26, 2026
8223b9f
docs: approve shared bot registry coding plan
KeepSilenceQP Jul 26, 2026
0bee076
Merge origin/main into feat/project-role-assignment (Gate G0 Base-sync)
KeepSilenceQP Jul 26, 2026
fd872ac
docs: record G0 base sync completion
KeepSilenceQP Jul 26, 2026
7294b2d
feat: add shared bot registry config contract
KeepSilenceQP Jul 26, 2026
ed67a52
docs: record Unit 1 completion
KeepSilenceQP Jul 26, 2026
db8e5b6
feat: register profiles in shared bot registry
KeepSilenceQP Jul 26, 2026
a0dfdc2
docs: record Unit 2 completion
KeepSilenceQP Jul 26, 2026
90cffd3
feat: register connected bot identity
KeepSilenceQP Jul 26, 2026
2609558
docs: record Unit 3 completion
KeepSilenceQP Jul 26, 2026
e283bd1
feat: add shared bot registry CLI
KeepSilenceQP Jul 26, 2026
8fe01bb
docs: record Unit 4 completion
KeepSilenceQP Jul 26, 2026
c2e137a
feat: parse named project bootstrap roles
KeepSilenceQP Jul 26, 2026
47b546a
docs: record Unit 5 completion
KeepSilenceQP Jul 26, 2026
a344413
feat: migrate project bootstrap to shared bot registry
KeepSilenceQP Jul 26, 2026
c4e837f
docs: record Unit 6 completion
KeepSilenceQP Jul 26, 2026
ee2667d
chore: add privacy gates for release artifacts
KeepSilenceQP Jul 26, 2026
d11b169
docs: record Unit 7 completion
KeepSilenceQP Jul 26, 2026
604e18d
docs: add coordinated registry migration runbook
KeepSilenceQP Jul 26, 2026
89b7631
docs: record Unit 9 completion
KeepSilenceQP Jul 26, 2026
01d676a
docs: record G8 review findings
KeepSilenceQP Jul 26, 2026
1d17f74
fix(config): serialize root updates and bootstrap preflight
KeepSilenceQP Jul 26, 2026
1577ec8
docs: record G8 review approval
KeepSilenceQP Jul 26, 2026
82ffd8d
docs: close Unit 10 live acceptance
KeepSilenceQP Jul 26, 2026
c700f7d
docs: close extended project role acceptance
KeepSilenceQP Jul 26, 2026
e5bbc4e
fix(ci): decouple privacy gate from repository history
KeepSilenceQP Jul 26, 2026
c70c89e
docs: record scoped source history remediation
KeepSilenceQP Jul 26, 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
47 changes: 20 additions & 27 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Enable pnpm
run: corepack enable
Expand Down Expand Up @@ -67,6 +69,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node
uses: actions/setup-node@v4
Expand All @@ -76,32 +80,21 @@ jobs:
- name: Prepare npm release layout
run: npm install --install-links=true

- name: Pack
id: pack
shell: bash
run: |
pack_output="$(npm pack --silent)"
printf '%s\n' "$pack_output"
pack_file="$(printf '%s\n' "$pack_output" | tail -n 1)"
echo "tarball=$PWD/$pack_file" >> "$GITHUB_OUTPUT"

- name: Install and start packed CLI
- name: Pack, privacy-scan, and clean-install one artifact
shell: bash
env:
PRIVACY_DENYLIST_JSON: ${{ secrets.LARK_BRIDGE_PRIVACY_DENYLIST_JSON }}
run: |
verify_dir="$(mktemp -d)"
npm install \
--prefix "$verify_dir" \
--install-links=true \
--ignore-scripts \
"${{ steps.pack.outputs.tarball }}"
installed="$verify_dir/node_modules/@penn.qp/lark-channel-bridge"
expected="$(node -p 'require("./package.json").version')"
actual="$(node "$installed/dist/cli.js" --version)"
test "$actual" = "$expected"
node -e '
const root = process.argv[1];
const channel = require(`${root}/node_modules/@larksuite/channel/package.json`);
const sdk = require(`${root}/node_modules/@larksuiteoapi/node-sdk/package.json`);
if (channel.version !== "0.4.0-qp.1") throw new Error(`unexpected channel ${channel.version}`);
if (!sdk.version) throw new Error("missing channel SDK");
' "$installed"
patterns="$RUNNER_TEMP/privacy-denylist.json"
artifact="$RUNNER_TEMP/verified-package.tgz"
if [ -z "${PRIVACY_DENYLIST_JSON:-}" ]; then
echo "::error::LARK_BRIDGE_PRIVACY_DENYLIST_JSON is not configured"
exit 1
fi
umask 077
printf '%s' "$PRIVACY_DENYLIST_JSON" > "$patterns"
unset PRIVACY_DENYLIST_JSON
npm run build
node tools/pack-and-verify.mjs \
--patterns-file "$patterns" \
--output "$artifact"
29 changes: 27 additions & 2 deletions .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
uses: actions/checkout@v6
with:
ref: ${{ env.RELEASE_TAG }}
fetch-depth: 0

- name: Set up Node and npm registry
uses: actions/setup-node@v6
Expand All @@ -54,5 +55,29 @@ jobs:
npm test
npm run typecheck

- name: Publish with npm Trusted Publishing
run: npm publish --access public --tag latest
- name: Build and verify the exact package artifact
id: package
shell: bash
env:
PRIVACY_DENYLIST_JSON: ${{ secrets.LARK_BRIDGE_PRIVACY_DENYLIST_JSON }}
run: |
patterns="$RUNNER_TEMP/privacy-denylist.json"
artifact="$RUNNER_TEMP/verified-package.tgz"
if [ -z "${PRIVACY_DENYLIST_JSON:-}" ]; then
echo "::error::LARK_BRIDGE_PRIVACY_DENYLIST_JSON is not configured"
exit 1
fi
umask 077
printf '%s' "$PRIVACY_DENYLIST_JSON" > "$patterns"
unset PRIVACY_DENYLIST_JSON
npm run build
node tools/pack-and-verify.mjs \
--patterns-file "$patterns" \
--output "$artifact"
echo "patterns=$patterns" >> "$GITHUB_OUTPUT"
echo "artifact=$artifact" >> "$GITHUB_OUTPUT"

- name: Publish the verified artifact with npm Trusted Publishing
env:
LARK_BRIDGE_PRIVACY_DENYLIST_FILE: ${{ steps.package.outputs.patterns }}
run: npm publish "${{ steps.package.outputs.artifact }}" --access public --tag latest
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Lark coding sessions:

| Area | What this fork adds | Problem it solves |
|---|---|---|
| **Multi-bot project bootstrap** | `/botAdmin` and `/project bootstrap` discover and invite the required Bridge bots, bind the project workspace, and dispatch the startup commands for a project group. | Starting a multi-bot project previously required several manual invitations, permission changes, and working-directory commands, with no single validated entry point. |
| **Multi-bot project environment preparation** | `/botAdmin` and `/project bootstrap` use explicit `--plan-writer` and `--implementer` roles to discover and invite selected Bridge bots, prepare their workspace, and persist the group's base actor assignment without starting a workflow. | Preparing a multi-bot project previously required several manual invitations, permission changes, and working-directory commands, with no single validated entry point. |
| **Native bot-to-bot handoff** | `lark-channel-bridge at-bot` validates the target against the current group's live bot list and sends a native structured mention with the current profile's bot identity. | Plain-text `@name`, hand-built mention JSON, stale `open_id` values, and replying to the wrong bot could silently lose a handoff while the agent still claimed it had notified the target. |
| **Per-group behavior** | Group-scoped operator prompts and four response modes (`mention-only`, `owner-default`, `all-messages`, and per-chat `owner-allowlist`) let each bot behave differently by group without opening access to everyone. | One global prompt and one global mention policy could not serve project groups with different roles; bots either stayed silent when the owner expected a reply or responded too broadly. |
| **Structured agent context** | The Bridge injects message, sender/bot identity, quote, card, and return-route context, and sends Bridge rules to Codex as developer instructions on every run. | Protocol rules mixed into ordinary user text were easier to ignore or misinterpret, especially for quoted messages, interactive cards, bot senders, and resumed Codex sessions. |
Expand Down Expand Up @@ -196,7 +196,7 @@ If a profile was created with the wrong agent kind, stop or unregister any match
| `/remove user @name`, `/remove admin @name`, `/remove group` | Remove access entries |
| `/remove owner-default group` | Remove the current group from the owner no-mention allowlist |
| `/botAdmin add <bot>`, `/botAdmin remove <bot>`, `/botAdmin list` | Manage bots allowed to run operational group commands |
| `/project bootstrap <workspace> <implementer>` | Discover/invite the project bots, bind the workspace, and start project-group collaboration |
| `/project bootstrap <workspace> --plan-writer <bot-name> --implementer <bot-name>` | In an ordinary group, prepare the chat-scoped workspace and persist the Decision Owner, receiving Coordinator, explicitly selected Implementer, and explicitly selected Plan Writer; the two role flags may appear in either order, Topic groups are rejected, and it does not start a workflow |
| `/stop` | Stop the current run, including the card stop button |
| `/timeout [N\|off\|default]` | Set or clear the current session idle watchdog |
| `/ps` | List local bridge processes |
Expand Down Expand Up @@ -273,6 +273,7 @@ The legacy `sandbox` field is still readable for old configs. After the bridge s
| `~/.lark-channel/profiles/<profile>/sessions.json` | Session state |
| `~/.lark-channel/profiles/<profile>/sessions.json.catalog.json` | Agent-aware session catalog |
| `~/.lark-channel/profiles/<profile>/workspaces.json` | Current and named workspace bindings |
| `~/.lark-channel/profiles/<profile>/projects.json` | Per-ordinary-group project workspace and role records, including injection-disabled state after incomplete preparation |
| `~/.lark-channel/profiles/<profile>/secrets.enc` | Profile-local encrypted secrets |
| `~/.lark-channel/profiles/<profile>/lark-cli/` | Profile-local lark-cli directory |
| `~/.lark-channel/profiles/<profile>/media/` | Attachment cache |
Expand Down
5 changes: 3 additions & 2 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

| 领域 | 本 Fork 新增的能力 | 解决的问题 |
|---|---|---|
| **多 Bot 项目启动** | `/botAdmin` 和 `/project bootstrap` 可以发现并邀请所需的 Bridge Bot、绑定项目工作目录,并在项目群中派发启动命令。 | 过去启动多 Bot 项目需要人工逐个拉 Bot、改权限、切目录和发命令,没有一个经过校验的统一入口。 |
| **多 Bot 项目环境准备** | `/botAdmin` 和 `/project bootstrap` 通过显式 `--plan-writer` 与 `--implementer` 角色发现并邀请指定 Bridge Bot、准备工作目录并保存群级基础角色,但不会自动启动工作流。 | 过去准备多 Bot 项目需要人工逐个拉 Bot、改权限、切目录和记录角色,没有一个经过校验的统一入口。 |
| **原生 Bot-to-Bot 交接** | `lark-channel-bridge at-bot` 会用当前群实时 Bot 列表校验目标,并以当前 profile 的 Bot 身份发送飞书原生结构化 mention。 | 纯文本 `@名字`、手拼 mention JSON、过期的 `open_id` 或选错回传对象,都可能让交接静默丢失,但 Agent 仍误以为已经通知成功。 |
| **按群定制行为** | 支持按群加载 operator prompt,并提供 `mention-only`、`owner-default`、`all-messages`、按群 `owner-allowlist` 四种响应模式,不需要为了免 @ 而向所有群成员开放 Bot。 | 一套全局 Prompt 和全局 @ 策略无法满足不同项目群的角色分工;Bot 可能在 owner 希望它响应时保持沉默,或响应范围过大。 |
| **结构化 Agent 上下文** | Bridge 会注入消息、发送者/Bot 身份、引用消息、交互卡片和回传路由信息,并在每次 Codex run 中用 developer instructions 传递 Bridge 规则。 | 把协议规则混在普通用户文本里更容易被忽略或误解,尤其是在引用回复、卡片、Bot 发送者和 Codex 恢复会话场景。 |
Expand Down Expand Up @@ -195,7 +195,7 @@ lark-channel-bridge profile export <name> --include-secrets --yes
| `/remove user @某人`, `/remove admin @某人`, `/remove group` | 移除访问控制条目 |
| `/remove owner-default group` | 从 owner 无 @ 响应名单中移除当前群 |
| `/botAdmin add <Bot>`, `/botAdmin remove <Bot>`, `/botAdmin list` | 管理可以执行群运维命令的 Bot |
| `/project bootstrap <workspace> <implementer>` | 发现/邀请项目 Bot、绑定工作目录并启动项目群协作 |
| `/project bootstrap <workspace> --plan-writer <bot-name> --implementer <bot-name>` | 在普通群中准备 chat 级 workspace,并保存 Decision Owner、命令接收 Coordinator、显式指定的 Implementer 和 Plan Writer;两个角色 flag 顺序任意,Topic 群会被拒绝,也不会自动启动工作流 |
| `/stop` | 停止当前 run,也可点卡片停止按钮 |
| `/timeout [N\|off\|default]` | 设置或清除当前会话的 idle watchdog |
| `/ps` | 列出本机 bridge 进程 |
Expand Down Expand Up @@ -272,6 +272,7 @@ bridge 会检查所选目录存在、是目录,并且不是 `/`、Home 根、
| `~/.lark-channel/profiles/<profile>/sessions.json` | 会话状态 |
| `~/.lark-channel/profiles/<profile>/sessions.json.catalog.json` | agent-aware 会话索引 |
| `~/.lark-channel/profiles/<profile>/workspaces.json` | 当前和命名工作空间绑定 |
| `~/.lark-channel/profiles/<profile>/projects.json` | 按普通群保存的项目 workspace 与角色记录,并记录不完整准备后的注入禁用状态 |
| `~/.lark-channel/profiles/<profile>/secrets.enc` | profile 本地加密 secret |
| `~/.lark-channel/profiles/<profile>/lark-cli/` | 当前 profile 的 lark-cli 目录 |
| `~/.lark-channel/profiles/<profile>/media/` | 附件缓存 |
Expand Down
Loading
Loading