Skip to content

Commit fc82b78

Browse files
committed
feat: add release gates and pty preflight
1 parent d62e70d commit fc82b78

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2382
-253
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
BOT_TOKEN=123456789:telegram-token-from-botfather
2+
TELEGRAM_EXPECTED_USERNAME=
3+
TELEGRAM_SMOKE_CHAT_ID=
24
ALLOWED_USER_IDS=123456789,987654321
35
PROACTIVE_USER_IDS=123456789
46
STATE_FILE=.codex-telegram-claws-state.json

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
node-version: [20, 22]
14+
env:
15+
BOT_TOKEN: "ci-bot-token"
16+
ALLOWED_USER_IDS: "1"
17+
CODEX_COMMAND: "node"
18+
CODEX_WORKDIR: "."
19+
WORKSPACE_ROOT: "."
20+
GITHUB_DEFAULT_WORKDIR: "."
21+
STATE_FILE: ".codex-telegram-claws-state.json"
22+
MCP_SERVERS: "[]"
23+
SHELL_ENABLED: "false"
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: ${{ matrix.node-version }}
30+
cache: npm
31+
32+
- run: npm ci
33+
- run: npm run check
34+
- run: npm run lint
35+
- run: npm run format:check
36+
- run: npm test
37+
- run: npm run healthcheck

.github/workflows/release.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
env:
14+
BOT_TOKEN: "ci-bot-token"
15+
ALLOWED_USER_IDS: "1"
16+
CODEX_COMMAND: "node"
17+
CODEX_WORKDIR: "."
18+
WORKSPACE_ROOT: "."
19+
GITHUB_DEFAULT_WORKDIR: "."
20+
STATE_FILE: ".codex-telegram-claws-state.json"
21+
MCP_SERVERS: "[]"
22+
SHELL_ENABLED: "false"
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- uses: actions/setup-node@v4
27+
with:
28+
node-version: 22
29+
cache: npm
30+
31+
- run: npm ci
32+
- run: npm run ci
33+
34+
- name: Publish GitHub release
35+
uses: softprops/action-gh-release@v2
36+
with:
37+
generate_release_notes: true
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Telegram Smoke
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
smoke:
8+
runs-on: ubuntu-latest
9+
if: ${{ secrets.TELEGRAM_BOT_TOKEN != '' }}
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: 22
16+
cache: npm
17+
18+
- run: npm ci
19+
20+
- name: Telegram getMe smoke check
21+
env:
22+
BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
23+
TELEGRAM_EXPECTED_USERNAME: ${{ secrets.TELEGRAM_EXPECTED_USERNAME }}
24+
TELEGRAM_SMOKE_CHAT_ID: ${{ secrets.TELEGRAM_SMOKE_CHAT_ID }}
25+
run: npm run telegram:smoke

.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
.git/
3+
.env
4+
.codex-telegram-claws-state.json

.prettierrc.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"trailingComma": "none",
5+
"arrowParens": "always"
6+
}

AGENTS.md

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,54 @@
11
# Repository Guidelines
22

3-
## Project Structure & Module Organization
4-
This repository is currently minimal and does not yet include application code, tests, or build tooling. Until a concrete stack is added, keep contributions organized with a predictable layout:
3+
## Repo Structure
54

6-
- `src/` for production code
7-
- `tests/` for automated tests
8-
- `assets/` for static files such as images or fixtures
9-
- `docs/` for design notes or operational guides
5+
- `src/index.js`: application entrypoint and subsystem wiring.
6+
- `src/bot/`: Telegram handlers, formatting, command parsing, i18n, middleware.
7+
- `src/orchestrator/`: routing, MCP client, skill registry, GitHub/MCP skills.
8+
- `src/runner/`: Codex PTY/exec management and restricted shell execution.
9+
- `src/cron/`: scheduled proactive jobs.
10+
- `tests/`: Node built-in test suite, one `*.test.js` file per module area.
1011

11-
Keep modules small and grouped by feature. For example, place Telegram client code in `src/telegram/` and matching tests in `tests/telegram/`.
12+
## Start And Dev Commands
1213

13-
## Build, Test, and Development Commands
14-
No project-specific commands are defined yet. When adding tooling, expose a minimal, documented set of commands such as:
14+
- `npm install`: install dependencies.
15+
- `npm run start`: start the Telegram bot with the current `.env`.
16+
- `npm run dev`: run the bot in watch mode for local development.
1517

16-
- `npm install` or equivalent to install dependencies
17-
- `npm test` to run the full test suite
18-
- `npm run lint` to enforce style rules
19-
- `npm run dev` to start local development
18+
## Test Commands
2019

21-
If you introduce a different stack, update this file in the same change so contributors have one reliable entry point.
20+
- `npm test`: run the full unit test suite with `node --test`.
21+
- `npm run check`: run a syntax check on the entrypoint and fail fast on invalid JS.
22+
- `npm run healthcheck`: run the local runtime health check.
2223

23-
## Coding Style & Naming Conventions
24-
Use 4 spaces for indentation in Markdown, YAML, and Python-style formats; follow the formatter defaults for any language-specific toolchain you add. Prefer descriptive, lowercase directory names (`src/bot/`), `snake_case` for Python files, and `kebab-case` or framework-standard naming for frontend assets.
24+
## Lint And Format
2525

26-
Add formatting and linting early and run them before opening a PR. Keep files ASCII unless the file already requires Unicode.
26+
- `npm run lint`: run ESLint over source, tests, scripts, and local JS/CJS config files.
27+
- `npm run lint:fix`: apply safe ESLint fixes.
28+
- `npm run format`: run Prettier across the repository.
29+
- `npm run format:check`: verify formatting without writing changes.
30+
- Do not submit formatting-only churn or rewrap unrelated files.
2731

28-
## Testing Guidelines
29-
Place tests under `tests/` and mirror the source layout. Name test files after the unit under test, such as `tests/telegram/test_dispatcher.py` or `dispatcher.test.ts`. Cover new behavior and important edge cases; avoid merging untested logic.
32+
## Files And Paths You Must Not Change
3033

31-
Document the exact test command in the project README and here once the framework is chosen.
34+
- Do not edit `.git/` or `node_modules/`.
35+
- Do not commit or rewrite `.env`, secrets, Telegram tokens, or local session artifacts.
36+
- Do not manually edit `.codex-telegram-claws-state.json`; it is runtime state.
37+
- Avoid changing files outside this repository root, even when `/repo` or shell features reference other workspaces.
3238

33-
## Commit & Pull Request Guidelines
34-
There is no Git history in the current workspace, so no established commit pattern can be inferred. Use short, imperative commit messages and prefer Conventional Commit prefixes where helpful, such as `feat: add webhook handler` or `fix: guard empty update payload`.
39+
## Contribution Rules
3540

36-
Pull requests should include a clear summary, testing notes, and linked issue references when applicable. Include screenshots or sample bot interactions for user-facing changes.
41+
- Use ES Modules and keep new files under the existing feature-oriented layout.
42+
- Keep user-facing bot copy in English by default. Localized strings must go through `src/bot/i18n.js`.
43+
- Prefer focused changes. Do not mix feature work with unrelated refactors.
44+
- Add or update tests for behavior changes in `tests/`.
3745

38-
## Configuration & Secrets
39-
Do not commit API tokens, session files, or `.env` values. Keep local configuration in ignored files and document required environment variables in `README.md`.
46+
## Required Verification Before Commit
47+
48+
- Run `npm run check`.
49+
- Run `npm run lint`.
50+
- Run `npm run format:check`.
51+
- Run `npm test`.
52+
- Run `npm run healthcheck`.
53+
- Review `git diff --stat` and `git status --short` for accidental edits.
54+
- If bot commands or behavior changed, update `README.md` and include a Telegram usage example in the PR or commit notes.

README.md

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,30 @@ Development mode:
7373
npm run dev
7474
```
7575

76-
Sanity check:
76+
Validation:
7777

7878
```bash
7979
npm run check
80+
npm run lint
81+
npm run format:check
8082
npm test
83+
npm run healthcheck
8184
```
8285

86+
## Development Commands
87+
88+
- `npm run start` - start the bot
89+
- `npm run dev` - watch mode for local development
90+
- `npm run check` - syntax validation
91+
- `npm run lint` - ESLint for source, tests, scripts, and local JS/CJS config files
92+
- `npm run lint:fix` - apply safe lint fixes
93+
- `npm run format` - format repository files with Prettier
94+
- `npm run format:check` - verify formatting
95+
- `npm test` - run the full test suite
96+
- `npm run healthcheck` - static runtime readiness check
97+
- `npm run healthcheck:strict` - stricter production-oriented health check
98+
- `npm run telegram:smoke` - live Telegram API smoke test when a real bot token is available
99+
83100
## Architecture
84101

85102
```text
@@ -114,6 +131,31 @@ This prevents:
114131
- extra latency/token/tool cost
115132
- context drift from two independent MCP execution surfaces
116133

134+
## Subagents
135+
136+
In this repository, "subagent" means a dedicated skill executor behind the router, not a second free-form Codex session.
137+
138+
Current subagents:
139+
140+
- `github` skill - local git actions, repo creation through GitHub API, and test job tracking
141+
- `mcp` skill - explicit MCP server inspection, enable/disable, tool listing, and tool calls
142+
143+
How they are triggered:
144+
145+
- Explicit commands always go straight to the matching subagent:
146+
- `/gh ...` -> GitHub skill
147+
- `/mcp ...` -> MCP skill
148+
- Plain text may also route to a subagent when the router sees a supported GitHub-style request such as `git push`, `commit`, or `run test`
149+
- Everything else falls back to Codex CLI
150+
151+
Where this happens:
152+
153+
- Router decision order: [router.js](/Users/ding/Documents/Code/Github/codex-telegram-claws/src/orchestrator/router.js)
154+
- Skill toggles per chat: [skillRegistry.js](/Users/ding/Documents/Code/Github/codex-telegram-claws/src/orchestrator/skillRegistry.js)
155+
- Telegram command entrypoints: [handlers.js](/Users/ding/Documents/Code/Github/codex-telegram-claws/src/bot/handlers.js)
156+
157+
Operationally, subagents are the bot's control plane. Codex remains the coding execution plane.
158+
117159
## Commands
118160

119161
General:
@@ -192,6 +234,7 @@ PTY output is streamed with throttled `editMessageText` updates.
192234
- quote block (if `REASONING_RENDER_MODE=quote`)
193235
- If `node-pty` cannot spawn on the current host, the runner falls back to `codex exec` for per-request execution
194236
- In `codex exec` fallback mode, Telegram output is cleaned to hide the Codex banner, raw tool trace, `mcp startup`, and duplicate `tokens used` footer
237+
- On macOS, startup now auto-repairs `node-pty` helper execute permissions before the first PTY session
195238

196239
## Project-Scoped Conversation State
197240

@@ -262,6 +305,33 @@ GITHUB_DEFAULT_BRANCH=main
262305
E2E_TEST_COMMAND=npx playwright test --reporter=line
263306
```
264307

308+
## CI And Release Automation
309+
310+
GitHub Actions now includes:
311+
312+
- `CI` workflow on push and pull request
313+
- `Telegram Smoke` manual workflow for live bot-token validation when repository secrets are configured
314+
- `Release` workflow on `v*` tags, which reruns validation and publishes a GitHub Release
315+
316+
Repository secrets for live smoke checks:
317+
318+
- `TELEGRAM_BOT_TOKEN`
319+
- `TELEGRAM_EXPECTED_USERNAME` (optional)
320+
- `TELEGRAM_SMOKE_CHAT_ID` (optional)
321+
322+
Recommended local release gate:
323+
324+
```bash
325+
npm run ci
326+
node scripts/healthcheck.js --strict --telegram-live
327+
```
328+
329+
Release references:
330+
331+
- [operations.md](/Users/ding/Documents/Code/Github/codex-telegram-claws/docs/operations.md)
332+
- [release.md](/Users/ding/Documents/Code/Github/codex-telegram-claws/docs/release.md)
333+
- [ecosystem.config.cjs](/Users/ding/Documents/Code/Github/codex-telegram-claws/ecosystem.config.cjs)
334+
265335
## Security Baseline
266336

267337
- Whitelist-only access (`ALLOWED_USER_IDS`) is mandatory
@@ -275,6 +345,21 @@ E2E_TEST_COMMAND=npx playwright test --reporter=line
275345
- If you allow write commands, mark high-risk prefixes in `SHELL_DANGEROUS_COMMANDS` and require `/sh --confirm ...`
276346
- Prefer least-privilege GitHub PAT
277347

348+
## Operations
349+
350+
The recommended production supervisor is PM2.
351+
352+
Basic flow:
353+
354+
```bash
355+
pm2 start ecosystem.config.cjs
356+
pm2 status codex-telegram-claws
357+
pm2 logs codex-telegram-claws
358+
pm2 restart codex-telegram-claws
359+
```
360+
361+
Run exactly one polling process per bot token.
362+
278363
## Should You Enable `/sh`?
279364

280365
Usually not for general users. Codex itself can run commands as part of a coding task, so `/sh` is not required for normal code-edit workflows.
@@ -305,7 +390,7 @@ Telegram can manage runtime usage of Bot-side MCP and skills, but not install ar
305390
- **MCP failures**: run `/mcp tools <server>` first to validate server availability
306391
- **GitHub API failures**: verify `GITHUB_TOKEN` scope (`repo`) and account permissions
307392
- **Duplicate MCP suspicion**: ensure coding tasks are routed directly to Codex, and bot MCP is used only for `/mcp`
308-
- **`posix_spawnp failed`**: this means PTY spawn is blocked on the host; the runner will fall back to `codex exec`
393+
- **`posix_spawnp failed`**: this usually means the `node-pty` helper lost execute permissions; startup now auto-repairs it, and `npm run healthcheck` reports the result
309394

310395
## Reference
311396

docs/operations.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Operations Guide
2+
3+
## Process Supervision
4+
5+
The recommended production supervisor is PM2. This bot uses Telegram long polling, so run exactly one instance per bot token.
6+
7+
Start:
8+
9+
```bash
10+
npm install
11+
cp .env.example .env
12+
pm2 start ecosystem.config.cjs
13+
```
14+
15+
Common PM2 commands:
16+
17+
```bash
18+
pm2 status codex-telegram-claws
19+
pm2 logs codex-telegram-claws
20+
pm2 restart codex-telegram-claws
21+
pm2 stop codex-telegram-claws
22+
pm2 save
23+
```
24+
25+
## Health Checks
26+
27+
Static health check:
28+
29+
```bash
30+
npm run healthcheck
31+
```
32+
33+
Strict health check:
34+
35+
```bash
36+
npm run healthcheck:strict
37+
```
38+
39+
Optional Telegram live check:
40+
41+
```bash
42+
node scripts/healthcheck.js --strict --telegram-live
43+
```
44+
45+
What the health check validates:
46+
47+
- workspace and runner directories exist
48+
- the state file directory is writable
49+
- the configured Codex command can be resolved
50+
- `node-pty` helper permissions are valid
51+
- optional live Telegram API authentication
52+
53+
## Deployment Notes
54+
55+
- Keep exactly one polling process per bot token.
56+
- Run the bot under a restricted system user.
57+
- Keep `.env` outside version control.
58+
- Rotate Telegram and GitHub tokens if they are ever exposed.
59+
- If you reinstall dependencies on macOS, rerun `npm run healthcheck`; the bot now auto-repairs `node-pty` helper permissions on startup.

0 commit comments

Comments
 (0)