Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
bb83755
feat(messaging): add hook scaffold and channel manifests
sandl99 May 22, 2026
7f79ccf
fix(messaging): allow shared hook output values
sandl99 May 22, 2026
3a92503
feat(messaging): declare enrollment hooks
sandl99 May 22, 2026
b8aa2e6
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 22, 2026
ab94308
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 22, 2026
c044b80
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 23, 2026
ab564a0
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 23, 2026
1e64396
Merge remote-tracking branch 'origin/main' into HEAD
sandl99 May 25, 2026
b96f5af
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 25, 2026
51e9591
feat(messaging): add manifest compiler (#4069)
sandl99 May 25, 2026
d8947ec
fix(messaging): address review feedback
sandl99 May 25, 2026
b030f4a
fix(messaging): inline merge key guard
sandl99 May 25, 2026
710e793
fix(messaging): validate merge subtrees
sandl99 May 25, 2026
458b885
fix(messaging): implement channel hooks and split applier
sandl99 May 25, 2026
4e78355
refactor(messaging): move policy keys into manifests
sandl99 May 25, 2026
4b0b67f
fix(messaging): include policy keys in applier context
sandl99 May 25, 2026
34fcf23
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 25, 2026
e2e31dc
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 25, 2026
7e6464d
fix(messaging): harden channel enrollment and build paths
cv May 25, 2026
ba7c0d5
fix(messaging): complete channel manifest hardening
cv May 25, 2026
55c4b57
fix(messaging): validate agent config render targets
cv May 25, 2026
812defe
fix(messaging): keep wechat hook dependencies injected
cv May 25, 2026
b602fc7
fix(messaging): keep token paste dependencies injected
cv May 25, 2026
accf1e3
refactor(messaging): unify validation hook phase
sandl99 May 26, 2026
5953299
revert(messaging): restore separate validation phases
sandl99 May 26, 2026
352855b
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 26, 2026
bb1cb78
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 26, 2026
6cd7dd3
feat(messaging): migrate enrollment to manifest hooks
sandl99 May 26, 2026
7027847
fix(messaging): address enrollment review feedback
sandl99 May 26, 2026
ee19d10
fix(messaging): gate channels on required inputs
sandl99 May 26, 2026
226f6ca
fix(messaging): preserve telegram reachability UX
sandl99 May 26, 2026
accfbd8
fix(messaging): run telegram reachability from manifest
sandl99 May 26, 2026
8e2c86b
Merge remote-tracking branch 'origin/u/sdang/3896-phase-2-messaging-e…
sandl99 May 26, 2026
63f3641
fix(onboard): pass sandbox name to messaging plans
sandl99 May 26, 2026
64945cb
fix(messaging): plan channel adds from manifests
sandl99 May 26, 2026
db55fe2
refactor(onboard): remove legacy messaging enrollment
sandl99 May 26, 2026
4ebd51b
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 26, 2026
c087d21
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 27, 2026
5daef1c
test(messaging): fix Hermes env helper calls
sandl99 May 27, 2026
12aac9f
Merge remote-tracking branch 'origin/u/sdang/messaging-hooks-channels…
sandl99 May 27, 2026
81b5f10
fix(slack): prompt for allowed channels
sandl99 May 27, 2026
0002ec5
fix(messaging): validate non-interactive enrollment hooks
sandl99 May 27, 2026
31dc207
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 28, 2026
91ad566
Merge branch 'u/sdang/messaging-hooks-channels-3993-3994' into u/sdan…
sandl99 May 28, 2026
303faa4
fix(messaging): bound telegram reachability probe
sandl99 May 28, 2026
51fd119
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 28, 2026
9807d4b
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 29, 2026
f5f2317
Merge branch 'u/sdang/messaging-hooks-channels-3993-3994' into u/sdan…
sandl99 May 29, 2026
701c3d3
Merge remote-tracking branch 'origin/u/sdang/3896-phase-2-messaging-e…
sandl99 May 29, 2026
498e9eb
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 29, 2026
7651b92
Merge branch 'u/sdang/messaging-hooks-channels-3993-3994' into u/sdan…
sandl99 May 29, 2026
47de166
refactor(messaging): simplify workflow planner
sandl99 May 29, 2026
686b136
Merge remote-tracking branch 'origin' into u/sdang/3896-phase-2-messa…
sandl99 May 29, 2026
98564a5
Merge remote-tracking branch 'origin/u/sdang/messaging-hooks-channels…
sandl99 May 29, 2026
63c1601
Merge remote-tracking branch 'origin/u/sdang/3896-phase-2-messaging-e…
sandl99 May 29, 2026
7d05b57
refactor(messaging): simplify channel compiler context
sandl99 May 29, 2026
b68bf7f
merge: u/sdang/messaging-hooks-channels-3993-3994
sandl99 May 29, 2026
52d08ce
fix(messaging): keep setup plan in host env
sandl99 May 29, 2026
020e53e
feat(messaging): persist manifest setup state
sandl99 May 29, 2026
0f2d824
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
cv May 30, 2026
52ac6fb
Merge branch 'main' into u/sdang/messaging-hooks-channels-3993-3994
sandl99 Jun 1, 2026
e33ee73
Merge branch 'u/sdang/messaging-hooks-channels-3993-3994' of github.c…
sandl99 Jun 1, 2026
d9f6f83
fix(messaging): move telegram alias enrollment to hook
sandl99 Jun 1, 2026
6f707db
fix(onboard): restore linux gateway cleanup guidance
sandl99 Jun 1, 2026
82c2854
fix(messaging): preserve rejected telegram enrollment
sandl99 Jun 1, 2026
b88e110
fix(messaging): restore telegram skip for fake add-remove e2e
sandl99 Jun 1, 2026
ac3c8bc
Merge remote-tracking branch 'origin/main' into u/sdang/3896-phase-2-…
sandl99 Jun 1, 2026
26bd4ce
Merge remote-tracking branch 'origin/main' into u/sdang/3896-phase-2-…
sandl99 Jun 2, 2026
4017a4c
refactor(messaging): move slack validation into hooks
sandl99 Jun 2, 2026
d999e18
merge: origin/main into messaging enrollment
sandl99 Jun 4, 2026
752ace3
feat(messaging): persist channel manifest plans (#4536)
sandl99 Jun 4, 2026
0538b97
test(e2e): accept wechat build-step plan entries
sandl99 Jun 4, 2026
d5cc5d1
Merge remote-tracking branch 'origin/main' into u/sdang/3896-phase-2-…
sandl99 Jun 5, 2026
58a11cb
Merge branch 'main' into u/sdang/3896-phase-2-messaging-enrollment
cv Jun 5, 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
6 changes: 4 additions & 2 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ _global_cleanup() {
}
trap _global_cleanup EXIT

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
_INSTALLER_SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "${_INSTALLER_SOURCE}")" && pwd)"
_INSTALLER_SCRIPT_PATH="${SCRIPT_DIR}/$(basename "${_INSTALLER_SOURCE}")"

resolve_repo_root() {
local base="${NEMOCLAW_REPO_ROOT:-$SCRIPT_DIR}"
Expand Down Expand Up @@ -2275,7 +2277,7 @@ ensure_docker() {
if installer_non_interactive \
&& [ "${NEMOCLAW_DOCKER_GROUP_REACTIVATED:-}" != "1" ] \
&& command -v sg >/dev/null 2>&1; then
local self="${BASH_SOURCE[0]:-$0}"
local self="${NEMOCLAW_INSTALLER_STAGED:-${_INSTALLER_SCRIPT_PATH:-${BASH_SOURCE[0]:-$0}}}"
if [ -n "$self" ] && [ -f "$self" ]; then
info "Reactivating docker group membership via 'sg docker' to continue non-interactive install."
export NEMOCLAW_DOCKER_GROUP_REACTIVATED=1
Expand Down
40 changes: 31 additions & 9 deletions src/lib/actions/sandbox/policy-channel-conflict.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const defs = D("agent/defs.js");
const rebuild = D("actions/sandbox/rebuild.js");
const processRecovery = D("actions/sandbox/process-recovery.js");
const onboardSession = D("state/onboard-session.js");
const slackValidation = D("actions/sandbox/slack-channel-validation.js");
const policy = D("policy/index.js");
const { hashCredential } = D("security/credential-hash.js") as {
hashCredential: (v: string) => string | null;
Expand Down Expand Up @@ -93,6 +92,19 @@ function conflictPromptShown(): boolean {
beforeEach(() => {
spies = [];
delete process.env.NEMOCLAW_NON_INTERACTIVE;
delete process.env.TELEGRAM_BOT_TOKEN;
delete process.env.TELEGRAM_ALLOWED_IDS;
delete process.env.TELEGRAM_REQUIRE_MENTION;
delete process.env.SLACK_BOT_TOKEN;
delete process.env.SLACK_APP_TOKEN;
delete process.env.SLACK_ALLOWED_USERS;
delete process.env.SLACK_ALLOWED_CHANNELS;
delete process.env.NEMOCLAW_SKIP_TELEGRAM_REACHABILITY;
delete process.env.NEMOCLAW_SKIP_SLACK_AUTH_VALIDATION;
delete process.env.WECHAT_BOT_TOKEN;
delete process.env.WECHAT_ACCOUNT_ID;
delete process.env.WECHAT_BASE_URL;
delete process.env.WECHAT_USER_ID;

logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
errSpy = vi.spyOn(console, "error").mockImplementation(() => undefined);
Expand Down Expand Up @@ -151,10 +163,8 @@ beforeEach(() => {
vi.spyOn(processRecovery, "executeSandboxExecCommand").mockReturnValue(null);
vi.spyOn(processRecovery, "executeSandboxCommand").mockReturnValue(null);

// Slack add runs a credential validation (auth.test-style) before the
// conflict check; that is its own concern and would otherwise probe Slack.
// Stub it to pass so scenario 11 can reach the conflict logic.
vi.spyOn(slackValidation, "validateSlackChannelCredentials").mockReturnValue({ ok: true });
process.env.NEMOCLAW_SKIP_TELEGRAM_REACHABILITY = "1";
process.env.NEMOCLAW_SKIP_SLACK_AUTH_VALIDATION = "1";

// onboard-session for the wechat host-qr branch.
vi.spyOn(onboardSession, "loadSession").mockReturnValue(null);
Expand All @@ -165,7 +175,19 @@ afterEach(() => {
vi.restoreAllMocks();
for (const s of spies) s.mockRestore();
delete process.env.NEMOCLAW_NON_INTERACTIVE;
delete process.env.NEMOCLAW_SKIP_TELEGRAM_REACHABILITY;
delete process.env.NEMOCLAW_SKIP_SLACK_AUTH_VALIDATION;
delete process.env.TELEGRAM_BOT_TOKEN;
delete process.env.TELEGRAM_ALLOWED_IDS;
delete process.env.TELEGRAM_REQUIRE_MENTION;
delete process.env.SLACK_BOT_TOKEN;
delete process.env.SLACK_APP_TOKEN;
delete process.env.SLACK_ALLOWED_USERS;
delete process.env.SLACK_ALLOWED_CHANNELS;
delete process.env.WECHAT_BOT_TOKEN;
delete process.env.WECHAT_ACCOUNT_ID;
delete process.env.WECHAT_BASE_URL;
delete process.env.WECHAT_USER_ID;
});

describe("addSandboxChannel cross-sandbox conflict check (#4305)", () => {
Expand Down Expand Up @@ -397,8 +419,8 @@ describe("addSandboxChannel cross-sandbox conflict check (#4305)", () => {
},
],
});
// acquireHostQrChannel short-circuits on a cached token; supply account
// metadata so the wechat cached-token branch does not bail.
// The hook planner skips non-interactive host-QR enrollment, but the
// conflict guard should still see a cached WeChat credential.
getCredentialMock.mockImplementation((key: string) =>
key === "WECHAT_BOT_TOKEN" ? wechatToken : null,
);
Expand Down Expand Up @@ -535,8 +557,8 @@ describe("addSandboxChannel cross-sandbox conflict check (#4305)", () => {

// Scenario 11
it("slack two-token channel: matching SLACK_BOT_TOKEN hash is detected", async () => {
const slackBot = "test-slack-bot-token";
const slackApp = "test-slack-app-token";
const slackBot = "xoxb-test-slack-bot-token";
const slackApp = "xapp-test-slack-app-token";
const slackBotHash = hashCredential(slackBot) as string;
arrangeRegistry({
current: { name: "alpha", messagingChannels: [] },
Expand Down
Loading
Loading