Skip to content
Open
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
90 changes: 54 additions & 36 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Generated:** 2025-01-20T00:00:00Z
**Branch:** main
**Refresh:** reconciled against actual file tree and `plans/*`; verified scheduled event routing, config loader, handler symbols, manual `/zai update-agents` command, action.yml inputs, and test coverage. Fixed stale workflow filenames (replaced nonexistent `code-review.yml` with actual `zai-code-bot.yml`, `zai-agents-init-example.yml`). Confirmed: scheduled test coverage exists (`tests/handlers/scheduled.test.js`, `tests/scheduled-config.test.js`, `tests/repository-context.test.js`, `tests/agents-validation.test.js`); `docs/scheduled-tasks.md` present; README updated with scheduled-tasks section and `/zai update-agents` command.
**Refresh:** reconciled against actual file tree, source files, `plans/*`, and test coverage. Verified three event flows (PR auto-review, `/zai` commands, scheduled tasks), handler registry, config loader, agents-validation guardrail, action.yml inputs, workflow filenames, code-scope.js exports, and auth.js permissive policy. Fixed stale `calculateTokenBudget` reference (function does not exist in `code-scope.js`; actual exports are `extractWindow`, `extractTargetBlock`, `extractEnclosingBlock`). Confirmed workflow filenames (`zai-code-bot.yml`, `zai-agents-update.yml`, `zai-agents-init-example.yml`).

## OVERVIEW
JavaScript GitHub Action with three event flows: (1) PR auto-review, (2) collaborator-gated `/zai` PR comment commands, and (3) cron-triggered scheduled tasks (`.zai-scheduled.yml`) that regenerate AGENTS.md files and open PRs. Runtime executes bundled `dist/index.js`; maintained logic lives in `src/index.js` plus modular services in `src/lib/*`.
Expand All @@ -14,15 +14,16 @@ zai-code-bot/
├── src/lib/ # Commands/auth/context/comments/api/services
├── src/lib/events.js # Event-type detection incl. `schedule` (cron) routing
├── src/lib/commands.js # `/zai` parser + allowlist (incl. `update-agents`)
├── src/lib/auth.js # Collaborator/fork authorization (currently permissive)
├── src/lib/auto-review.js # Large PR batching and synthesis
├── src/lib/changed-files.js # Paginated changed-files fetch (3000 file limit)
├── src/lib/pr-context.js # Shared PR context fetch (files, content at ref, refs)
├── src/lib/code-scope.js # Token-budget calculation for prompt sizing
├── src/lib/code-scope.js # Window/block extraction for prompt scoping
├── src/lib/context.js # Changed-file fetch + truncation/range helpers
├── src/lib/config/scheduled-config.js # Scheduled-task config loader (.zai-scheduled.yml)
├── src/lib/repository-context.js # Real repo context collection (tree + AGENTS.md discovery + key files)
├── src/lib/agents-validation.js # Hallucination guard: validates generated AGENTS.md vs real repo
├── src/lib/handlers/ # Command + scheduled handlers (ask/review/explain/describe/impact/help/scheduled)
├── src/lib/handlers/ # Command + scheduled handlers (see child AGENTS.md)
├── tests/ # Unit and integration coverage (Vitest v3)
├── dist/index.js # Generated ncc bundle executed by GitHub
├── dist/licenses.txt # Generated third-party licenses
Expand All @@ -49,13 +50,13 @@ zai-code-bot/
| Route events and command execution | `src/index.js` | `run()`, pull_request path, issue_comment command path, schedule path |
| Schedule event detection | `src/lib/events.js` | `getEventType` returns `schedule`; `shouldProcessEvent` always processes cron events |
| Parse commands and enforce allowlist | `src/lib/commands.js` | `/zai` parser, command normalization, help fallback; `update-agents` in allowlist |
| Authorization and fork policy | `src/lib/auth.js` | Collaborator checks and fork-safe behavior |
| Authorization and fork policy | `src/lib/auth.js` | Collaborator checks and fork-safe behavior; currently permissive (authorizes any identifiable user) |
| Comment/reaction behavior | `src/lib/comments.js` | Marker-based upsert, threaded reply (`replyToId`), reactions |
| API retry/error handling | `src/lib/api.js`, `src/lib/logging.js` | Retry policy, categorized safe errors |
| Large PR batching and synthesis | `src/lib/auto-review.js` | Batch creation, context limit handling, synthesis prompt |
| Paginated changed-files fetch | `src/lib/changed-files.js` | Handles GitHub's 3000 file API limit |
| Shared PR context fetch | `src/lib/pr-context.js` | `fetchPrFiles`, `fetchFileAtRef`, `resolvePrRefs`; user-safe fallbacks, size limits |
| Token budget calculation | `src/lib/code-scope.js` | Window extraction, enclosing block detection for prompt sizing |
| Code scope extraction | `src/lib/code-scope.js` | `extractWindow`, `extractTargetBlock`, `extractEnclosingBlock` for prompt scoping |
| Scheduled-task config loading | `src/lib/config/scheduled-config.js` | `loadScheduledConfig`, `getTasksToRun`, `validateAndNormalizeConfig`, `validateAgentsConfig`, `getGistUrl`; scoping fields (`context_paths`/`target_paths`/`exclude_paths`/budgets) |
| Scheduled-task execution | `src/lib/handlers/scheduled.js` | `handleScheduledEvent`, `handleUpdateAgentsTask` (grounded flow: context→prompt→validate→PR), `SCHEDULED_HANDLERS`; see child `src/lib/handlers/AGENTS.md` |
| Repository context for AGENTS.md gen | `src/lib/repository-context.js` | `collectRepositoryContext` (git tree + existing AGENTS.md discovery + key files, budgeted), `renderRepositoryContext` |
Expand Down Expand Up @@ -91,7 +92,9 @@ zai-code-bot/
| `fetchFileAtRef` | function | `src/lib/pr-context.js` | medium | File content at base/head ref, sliding-window scoping |
| `resolvePrRefs` | function | `src/lib/pr-context.js` | low | Resolves base/head refs for diff context |
| `MAX_PR_FILES_API_LIMIT` | constant | `src/lib/changed-files.js` | low | GitHub API ceiling (3000) |
| `calculateTokenBudget` | function | `src/lib/code-scope.js` | medium | Token/char budget sizing for prompts |
| `extractEnclosingBlock` | function | `src/lib/code-scope.js` | medium | Enclosing function/class block selection for prompt scoping |
| `extractWindow` | function | `src/lib/code-scope.js` | low | Target lines + surrounding window extraction |
| `extractTargetBlock` | function | `src/lib/code-scope.js` | low | Exact line range extraction |
| `getEventType` | function | `src/lib/events.js` | low | Event-type detection for routing (incl. `schedule`) |
| `shouldProcessEvent` | function | `src/lib/events.js` | low | Event filter; always-process gate for cron events |
| `loadScheduledConfig` | function | `src/lib/config/scheduled-config.js` | low | Parses `.zai-scheduled.yml` task config |
Expand All @@ -115,37 +118,52 @@ zai-code-bot/
## CONVENTIONS
- Edit maintained code in `src/`; do not hand-edit generated `dist/index.js`.
- After source changes, run `npm run build` and commit `dist/index.js` + `dist/licenses.txt`.
- Use marker-based idempotent comments; preserve marker constants and update semantics.
- Command responses should stay threaded to the invoking comment via `replyToId`.
- Keep security posture strict: collaborator/fork checks before command execution, no secret leakage.
- Use marker-based idempotent comments; preserve marker constants (`COMMENT_MARKER`, `PROGRESS_MARKER`, `GUIDANCE_MARKER`, `AUTH_MARKER`) and update semantics.
- Command responses must stay threaded to the invoking comment (`replyToId`); never post top-level comments for command replies.
- Authorization (`enforceCommandAuthorization`) must precede all command handler execution; fork PRs follow silent-block policy for non-identifiable users.
- Keep prompts bounded via `src/lib/code-scope.js` and `src/lib/context.js` truncation helpers; never pass raw unbounded patches into Z.ai prompts.
- Return user-safe errors via `src/lib/logging.js`; never surface raw exception internals or secrets in PR comments.
- External I/O (Z.ai, GitHub API) goes through `src/lib/api.js` and `src/lib/pr-context.js`, not ad-hoc calls in handlers.
- Scheduled AGENTS.md generation must pass through `validateGeneratedAgentFiles` before any PR is created (hallucination guard).
- Reaction lifecycle: `eyes` (acknowledge) → `eyes` (working — `REACTIONS.THINKING` maps to `'eyes'`) → `rocket` (success) / `-1` (failure).

## ANTI-PATTERNS (THIS PROJECT)
- Bypassing authorization/fork checks for command handlers.
- Executing command logic for non-PR issue comments.
- Allowing unbounded context payloads into prompts.
- Asking an LLM to "scan the repo" without providing real repo context (causes hallucinated AGENTS.md — PR #15 bug).
- Committing AGENTS.md output that references files/languages not present in the repo.
- Editing `dist/` manually or shipping source changes without rebuilt artifacts.
- Confusing consumer-facing workflow examples (README snippet) with this repo's own `.github/workflows/` runtime logic.
## ANTI-PATTERNS
- Running handler logic before auth/fork checks.
- Hand-editing `dist/index.js` instead of `src/` then rebuilding.
- Returning raw exception details to PR comments.
- Unbounded diff/context payloads in prompts.
- Bypassing `validateGeneratedAgentFiles` for AGENTS.md updates.
- Introducing hidden coupling between unrelated service modules.
- Posting top-level comments instead of threaded replies for command responses.
- Deleting integration assertions to make behavior changes pass.

## UNIQUE STYLES
- Event-first architecture: `src/index.js` orchestrates; `src/lib/*` isolates concerns.
- Reactions communicate command lifecycle (`eyes`/`thinking`/`rocket`/`x`).
- Continuity is encoded with hidden markers in comments, not external storage.
## TESTING
- Framework: Vitest v3 (globals: `describe`/`test`/`expect`); configured via `vitest.config.js`.
- Run: `npm test` → `vitest run --coverage`.
- Coverage uploaded to Codecov.
- Unit tests: `tests/*.test.js` and `tests/handlers/*.test.js`.
- Integration tests: `tests/integration/*.test.js` (command pipeline + PR auto-review lifecycle).
- When changing comment markers or command UX, update integration assertions immediately.
- See `tests/AGENTS.md` for the full test map.

## COMMANDS
```bash
npm install
npm test # vitest run --coverage
npm run build # ncc build src/index.js -o dist --license licenses.txt
npm audit --audit-level=moderate # security audit gate (CI)
```
After source changes: run `npm run build` and commit `dist/index.js` + `dist/licenses.txt` (CI fails on dist drift).
## KEY DOCS
| Document | Purpose |
|----------|---------|
| `ARCHITECTURE.md` | Layered architecture, dependency direction, life-of-request flows, invariant catalog |
| `CONTRIBUTING.md` | Contribution guide, build/release process, senior review checklists |
| `RUNBOOK.md` | Operational procedures, rollback steps, incident response |
| `SECURITY.md` | Authorization rules, fork policy, permission model |
| `docs/scheduled-tasks.md` | Scheduled-task configuration reference, cron syntax, troubleshooting |
| `README.md` | User-facing inputs, commands, quickstart, consumer workflow example |
| `src/lib/AGENTS.md` | Services-layer module guide |
| `src/lib/handlers/AGENTS.md` | Per-command handler guide |
| `tests/AGENTS.md` | Test strategy and suite layout |
| `tests/integration/AGENTS.md` | End-to-end pipeline test guide |

## NOTES
- CI (`.github/workflows/ci.yml`) enforces tests, build, dist drift, and security audit across Node 20 + 22.
- No linting/formatting configs (ESLint, Prettier) — rely on code review and CI gates.
- 7 command handlers + scheduled pipeline: `ask`, `review`, `explain`, `describe`, `impact`, `help`, plus `scheduled` (largest handler, drives cron tasks via `.zai-scheduled.yml`).
- Scheduled test coverage: `tests/handlers/scheduled.test.js`, `tests/scheduled-config.test.js`, `tests/repository-context.test.js`, `tests/agents-validation.test.js` (unit-level); end-to-end schedule integration test is still a gap.
- Scheduled-tasks configuration reference: `docs/scheduled-tasks.md`.
- Architecture and invariants catalog: `ARCHITECTURE.md`.
## GOTCHAS
- `dist/index.js` is the only artifact GitHub executes; CI `dist-drift` job fails on uncommitted `dist/` changes.
- GitHub's changed-files API caps at 3000 files (`MAX_PR_FILES_API_LIMIT`); coverage notes flag incomplete review beyond that ceiling.
- `REACTIONS.THINKING` maps to `'eyes'` (not a distinct emoji) — see `src/lib/comments.js`.
- Auth module (`src/lib/auth.js`) currently authorizes any identifiable user (permissive policy); fork non-identifiable users are silently blocked.
- `scheduled` handler is imported directly in `src/index.js`, not through the `/zai` HANDLERS map in `handlers/index.js`.
- The `handleUpdateAgentsTask` flow embeds a strict no-live-repo-access constraint in its prompt; the model receives only the collected context snapshot.
7 changes: 4 additions & 3 deletions src/lib/handlers/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Command handlers implement `/zai` behavior only after parsing + authorization; e
| `/zai describe` | `src/lib/handlers/describe.js` | File/directory description |
| `/zai impact` | `src/lib/handlers/impact.js` | Change impact analysis |
| `/zai help` | `src/lib/handlers/help.js` | Static help output with auth gate |
| `/zai update-agents` | `src/index.js` (`dispatchCommand`) | Manual AGENTS.md regen; reuses `handleUpdateAgentsTask` |
| `/zai update-agents` | `src/index.js` (`dispatchCommand`) | Manual AGENTS.md regen; reuses `handleUpdateAgentsTask` from `scheduled.js` |
| scheduled tasks | `src/lib/handlers/scheduled.js` | Largest module; cron-driven `.zai-scheduled.yml` tasks; grounded + validated AGENTS.md upgrades |
| Handler registry | `src/lib/handlers/index.js` | Dispatcher map consumed by runtime (note: `scheduled` is exported but not in the `/zai` HANDLERS map) |
| Handler registry | `src/lib/handlers/index.js` | Dispatcher map consumed by runtime (note: `scheduled` is exported but not in the `/zai` HANDLERS map; imported directly in `src/index.js`) |

## SCHEDULED MODULE (`scheduled.js`) KEY SYMBOLS
- `handleScheduledEvent` (entry) → `executeScheduledTask` (per-task) → `buildExecutionContext` → `getScheduledHandler` (registry lookup).
Expand All @@ -27,7 +27,7 @@ Command handlers implement `/zai` behavior only after parsing + authorization; e
## CONVENTIONS
- Keep command argument parsing explicit and reject invalid formats early.
- Always use threaded replies (`replyToId`) for command results.
- Reactions should reflect lifecycle: acknowledge -> work -> success/failure.
- Reactions should reflect lifecycle: acknowledge work success/failure.
- Keep prompts bounded via context truncation helpers; never pass raw unbounded patches.
- Return user-safe failures; log internal details through shared logging helpers.

Expand All @@ -46,3 +46,4 @@ Command handlers implement `/zai` behavior only after parsing + authorization; e
## NOTES
- Prefer adding helper functions within a handler module before introducing cross-handler coupling.
- Keep marker constants stable once tests depend on them.
- `handleUpdateAgentsTask` is testable via the `__callZaiForTest` injection seam (see `tests/handlers/scheduled.test.js`); use this to mock Z.ai responses without network calls.
13 changes: 7 additions & 6 deletions tests/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Repository test coverage mixes module-focused tests in `tests/*.test.js` and sce
tests/
├── *.test.js # Module-level tests for lib/runtime units
├── handlers/ # Handler-focused test cases (ask, explain, impact, review, scheduled)
├── helpers/ # Shared mocks and fixtures utilities
├── lib/ # Shared test helpers + code-scope tests
├── helpers/ # Shared mocks and fixtures utilities (mocks.js)
├── lib/ # Code-scope tests (code-scope.test.js)
├── fixtures/ # Static test payloads (issue-comment-event.json, pr-event.json)
└── integration/ # End-to-end command/review pipeline checks
```
Expand All @@ -22,23 +22,24 @@ tests/
| API and logging resilience | `tests/api.test.js`, `tests/logging.test.js` | Retry/error categorization |
| Context, PR fetch, and batching | `tests/context.test.js`, `tests/pr-context.test.js`, `tests/changed-files.test.js`, `tests/auto-review.test.js` | Diff scoping, file-at-ref fetch, paginated/batched review |
| Continuity and events | `tests/continuity.test.js`, `tests/events.test.js` | Hidden-marker state, event-type detection |
| Code scope and window extraction | `tests/lib/code-scope.test.js` | Token budget, enclosing block, window extraction |
| Code scope and window extraction | `tests/lib/code-scope.test.js` | Window extraction, enclosing block, target block |
| Describe handler | `tests/describe.test.js` | PR description generation |
| Scheduled pipeline | `tests/handlers/scheduled.test.js`, `tests/scheduled-config.test.js`, `tests/repository-context.test.js`, `tests/agents-validation.test.js` | Config load + `validateAgentsConfig` scoping; `parseFileUpdatesFromResponse`; grounded `handleUpdateAgentsTask` flow incl. hallucination rejection; repo-context collection (tree/budgets/globs); validation guards incl. PR #15 regression |
| Scheduled pipeline | `tests/handlers/scheduled.test.js`, `tests/scheduled-config.test.js`, `tests/repository-context.test.js`, `tests/agents-validation.test.js` | Config load + `validateAgentsConfig` scoping; `parseFileUpdatesFromResponse`; grounded `handleUpdateAgentsTask` flow incl. hallucination rejection (via `__callZaiForTest` seam); repo-context collection (tree/budgets/globs); validation guards incl. PR #15 regression |
| Scheduled pipeline (integration) | (pending) | End-to-end schedule event → context → Z.ai mock → validated PR is still a gap; unit coverage of the grounded flow exists via the `handleUpdateAgentsTask` seam (`__callZaiForTest`). |
| Full command pipeline | `tests/integration/command-pipeline.test.js` | Parse -> auth -> handler -> output contract |
| Full command pipeline | `tests/integration/command-pipeline.test.js` | Parse auth handler output contract |
| PR auto-review behavior | `tests/integration/pr-auto-review.test.js` | Marker upsert and PR event lifecycle |

## CONVENTIONS
- Test framework: Vitest v3 (uses vitest globals: describe/test/expect); configured via `vitest.config.js`.
- Keep tests deterministic with explicit mock payloads and marker assertions.
- Prefer scenario names that encode trigger + expected visible outcome.
- When changing comment markers or command UX, update integration snapshots/assertions immediately.
- Shared mock utilities live in `tests/helpers/mocks.js`; reuse rather than duplicating inline.

## ANTI-PATTERNS
- Deleting integration assertions to make behavior changes pass.
- Asserting only internal calls without validating user-visible output.
- Duplicating large fixtures inline when reusable fixtures already exist.
- Duplicating large fixtures inline when reusable fixtures already exist in `tests/fixtures/`.

## NOTES
- Test command: `npm test` → `vitest run --coverage`.
Expand Down
1 change: 1 addition & 0 deletions tests/integration/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Integration tests verify end-to-end GitHub event pipelines and visible bot behav
- Test the public behavior chain from event input to final comment/reaction outcome.
- Cover both happy paths and safety gates (non-PR comments, unauthorized users, empty diffs).
- Keep marker expectations explicit so idempotent update regressions are caught quickly.
- Shared event payloads in `tests/integration/fixtures/events.js` should be extended rather than duplicating inline JSON.

## ANTI-PATTERNS
- Replacing integration assertions with unit-level mocks only.
Expand Down