Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions .agentworkforce/agents/relay-feature-guardian/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ import guardian, {
} from './agent.ts';

const persona = JSON.parse(readFileSync(new URL('./persona.json', import.meta.url), 'utf8')) as {
integrations: Record<
string,
{ relayfileMount?: { requiredReadPaths?: unknown; writeOnlyPaths?: unknown } }
>;
inputs: { SLACK_CHANNEL: { default: string } };
memory: { enabled: boolean; scopes: string[]; ttlDays: number };
};

const manifestFeatures = [
Expand Down Expand Up @@ -318,6 +323,22 @@ describe('relay-feature-guardian runtime paths', () => {
expect(persona.inputs.SLACK_CHANNEL.default).toBe('C0AEKNLDNKW');
});

it('declares bounded manifest and memory reads plus configured Slack output', () => {
expect(persona.integrations.github?.relayfileMount).toEqual({
requiredReadPaths: ['/github/repos/AgentWorkforce/relay/.agentworkforce/features/**'],
writeOnlyPaths: [],
});
expect(persona.memory).toEqual({
enabled: true,
scopes: ['workspace'],
ttlDays: 14,
});
expect(persona.integrations.slack?.relayfileMount).toEqual({
requiredReadPaths: [],
writeOnlyPaths: ['/slack/channels/${SLACK_CHANNEL}/**'],
});
});

it('deduplicates an ambiguous post retry and advances after a saved receipt', async () => {
const transport = new IdempotentSlackTransport();
const restore = bindPreviewTransport(transport);
Expand Down
8 changes: 8 additions & 0 deletions .agentworkforce/agents/relay-feature-guardian/persona.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@
"github": {
"scope": {
"repo": "AgentWorkforce/relay"
},
"relayfileMount": {
"requiredReadPaths": ["/github/repos/AgentWorkforce/relay/.agentworkforce/features/**"],
"writeOnlyPaths": []
}
},
"slack": {
"scope": {
"paths": "/slack/channels/**"
},
"relayfileMount": {
"requiredReadPaths": [],
"writeOnlyPaths": ["/slack/channels/${SLACK_CHANNEL}/**"]
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `agent-relay integration` now discovers relayfile control-plane capabilities before sending API v3 headers, fails fast with upgrade and restart guidance for incompatible daemons, and safely replaces stale daemons when a compatible binary is installed.
- `AgentRelaySDK` now maps Relaycast lifecycle states onto its existing Swift presence states, so root-package consumers compile with Relaycast 6.1 and later while package-local builds remain compatible with 6.0.5.
- `relay-feature-guardian` now reads the scoped Relay clone, posts to its configured channel, and advances its exact, revision-safe cycle checkpoint only after a bounded wait returns a real Slack receipt, while safely reconciling retired manifest features.
- `relay-feature-guardian` now limits read mirrors to the feature manifest and workspace memory while keeping Slack write-only to its configured output channel, and advances its exact, revision-safe cycle checkpoint only after a bounded wait returns a real Slack receipt while safely reconciling retired manifest features.
- `agent-relay-broker` and `@agent-relay/utils` now preserve mise/asdf/rtx-style CLI shims when spawning provider workers, so Codex, Claude, Gemini, and other agent CLIs installed via a version manager receive their own permission flags (e.g. `--dangerously-bypass-approvals-and-sandbox`) instead of the manager binary rejecting them.

## [10.6.3] - 2026-07-17
Expand Down
Loading