diff --git a/AGENTS.md b/AGENTS.md index 3d2da45b8..aed814dbc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ - Use the words in `TERMINOLOGY.md`. Do not invent synonyms, overloaded terms, or long compound names when an existing term fits. - This is TypeScript/JavaScript, not Java. Prefer functions, plain objects, simple types, and small modules. Avoid class hierarchies, manager/factory names, and interface layers unless they solve a real problem; follow `policies/interface-design.md`. - Optimize for the next maintainer. Choose the smallest design that solves the proven problem, keep complexity local, and avoid speculative abstractions, configuration, extension points, and wrappers; follow `policies/correctness-complexity.md`. -- Write for normal humans. Code, names, docs, plans, and explanations should make sense without a PhD or an architecture lecture. If they do not, simplify them. +- Write docs, policies, plans, and explanations in ASD-STE100 English. Use common words, active voice, short sentences, and one idea per sentence. Keep required terms from `TERMINOLOGY.md` and explain them when needed. Remove other jargon. Use **pnpm**: `pnpm install`, `pnpm dev`, `pnpm test`, `pnpm typecheck`, `pnpm skills:check`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20e21d08a..efac889dd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,9 @@ pnpm docs:check pnpm release:check ``` -## Internal Documentation +## Documentation + +Write public and internal docs in ASD-STE100 English. Use common words, active voice, short sentences, and one idea per sentence. Keep required terms from `TERMINOLOGY.md`. Explain them when needed. Remove other jargon. Public docs have more rules in `packages/docs/src/content/docs/contribute/documentation-guidelines.md`. - `policies/` contains durable repo-wide engineering rules. - Package and module `README.md` files explain implemented architecture and diff --git a/packages/docs/src/content/docs/cli/_cli-template.md b/packages/docs/src/content/docs/cli/_cli-template.md index 9058a98eb..cae365fe1 100644 --- a/packages/docs/src/content/docs/cli/_cli-template.md +++ b/packages/docs/src/content/docs/cli/_cli-template.md @@ -1,6 +1,6 @@ --- title: CLI Page Template -description: Canonical structure for Junior CLI command pages. +description: Required structure for Junior CLI command pages. type: reference prerequisites: - /start-here/quickstart/ @@ -10,11 +10,11 @@ related: - /cli/snapshot-create/ --- -Use this template for `junior` command docs so readers get the same path from invocation to verification. +Use this template for `junior` command docs. Follow the writing rules in [Documentation Guidelines](/contribute/documentation-guidelines/). Give readers the same path from command to result. ## Usage -Show the canonical command invocation first. If the command accepts an optional path or flag, include one realistic second example. +Show the main command first. If the command accepts an optional path or flag, include one realistic second example. ## Extended usage @@ -22,11 +22,11 @@ Add optional path, subcommand, or flag examples only when they change how someon ## What it does -Explain the command outcome in one short paragraph, then list the specific files, directories, or runtime surfaces it touches. +Explain the command result in one short paragraph. Then list the files, directories, or parts of Junior that it changes. ## Failure behavior -Show one real error shape and explain what the reader should fix next. Prefer actionable messages over internal implementation details. +Show one real error and explain what the reader should fix next. Tell the reader what to do. Do not add internal design details. ## Verification diff --git a/packages/docs/src/content/docs/cli/chat.md b/packages/docs/src/content/docs/cli/chat.md index ab70a2073..42c8dc812 100644 --- a/packages/docs/src/content/docs/cli/chat.md +++ b/packages/docs/src/content/docs/cli/chat.md @@ -12,7 +12,7 @@ related: - /operate/observability/ --- -Use `junior chat` when you want to exercise Junior's agent runtime without sending a Slack message. The command runs from a project that already has `@sentry/junior` installed and uses the same app files, skills, plugins, model settings, and sandbox behavior as a normal agent turn. For a focused validation workflow, use [Local Agent Validation](/contribute/local-agent-validation/). +Use `junior chat` to test Junior without sending a Slack message. Run the command from a project that has `@sentry/junior` installed. It uses the same app files, skills, plugins, model settings, and sandbox behavior as a normal turn. For a focused test, use [Local Agent Validation](/contribute/local-agent-validation/). ## Usage @@ -34,13 +34,13 @@ pnpm exec junior chat -p "Summarize this repository" | -------------- | -------------------------------------------------- | | `-p ` | Sends one message, prints the response, and exits. | -Every `junior chat` invocation creates a fresh local conversation. Interactive mode keeps context only while that process is running; `-p` sends one isolated message and exits. +Each `junior chat` command creates a new local conversation. Interactive mode keeps context only while the process runs. The `-p` option sends one separate message and exits. ## State and environment `junior chat` does not require Slack request signing, Slack tokens, or a Slack channel. It still needs the model and tool environment required by the behavior you are testing, such as Vercel OIDC (`vercel env pull`) or `AI_GATEWAY_API_KEY`, plus any plugin provider credentials. -When neither `JUNIOR_STATE_ADAPTER` nor `REDIS_URL` is set, the command uses the in-memory state adapter so a new project can start a local session without Redis. Set `REDIS_URL` when you want local run state stored for diagnostics or to match your deployed app state behavior; the CLI still starts a new conversation on each invocation. +If `JUNIOR_STATE_ADAPTER` and `REDIS_URL` are not set, the command keeps state in memory. This lets a new project start without Redis. Set `REDIS_URL` to save local run state or to match the deployed app. The CLI still starts a new conversation for each command. The local actor is the `local-cli` user. When a provider needs user OAuth, the command prints the authorization link, waits for the browser callback, and then continues the same request. Keep the command running while you authorize. The public development URL and local dev server must be reachable for this relay; see [Local Agent Validation](/contribute/local-agent-validation/) for the setup and troubleshooting steps. diff --git a/packages/docs/src/content/docs/concepts/execution-model.md b/packages/docs/src/content/docs/concepts/execution-model.md index 5c057b0b6..46f0b9c65 100644 --- a/packages/docs/src/content/docs/concepts/execution-model.md +++ b/packages/docs/src/content/docs/concepts/execution-model.md @@ -13,7 +13,7 @@ related: Junior stores work before processing it. This lets a turn continue after a timeout, authorization prompt, or worker restart. -## Lifecycle +## How work moves through Junior 1. A Slack message, task, or plugin event arrives. 2. Junior validates and stores the work. @@ -34,14 +34,14 @@ Progress updates are status, not final replies. Text produced while calling tool ## Recovery -Junior checkpoints completed tool work and resumes from the latest saved state. This applies when: +Junior saves completed tool work. It resumes from the latest saved state when: - OAuth pauses a turn - work exceeds one execution window - a worker stops unexpectedly - delivery fails and can be retried -Sandbox files are not durable state and may disappear between attempts. +Sandbox files are temporary. They may disappear between attempts. ## Delivery Guarantees diff --git a/packages/docs/src/content/docs/contribute/documentation-guidelines.md b/packages/docs/src/content/docs/contribute/documentation-guidelines.md index dc2aa6450..6d4cca169 100644 --- a/packages/docs/src/content/docs/contribute/documentation-guidelines.md +++ b/packages/docs/src/content/docs/contribute/documentation-guidelines.md @@ -10,7 +10,7 @@ related: - /contribute/releasing/ --- -Junior public docs should help readers choose the right setup path, copy a working configuration, and verify behavior without reading internal implementation docs first. +Junior public docs must help readers choose a setup path, copy a working configuration, and check the result. Readers should not need to read internal design docs first. ## Page contract @@ -32,15 +32,17 @@ Choose one primary job per page: | Type | Use it for | | ----------------- | ------------------------------------------------------- | | `tutorial` | Step-by-step setup with verification. | -| `conceptual` | Mental model, tradeoff, or reading path. | +| `conceptual` | Core idea, choice, or reading path. | | `reference` | Fast lookup for config, commands, APIs, or contracts. | | `troubleshooting` | Symptom, first check, recovery order, and verification. | Avoid pages that mix tutorial, concept, and reference material unless the page is intentionally a short overview. -## Writing defaults +## Writing rules -Lead with what the reader should do or decide. Keep examples minimal but runnable, and label code fences with the target file when the snippet belongs in a file. +Use ASD-STE100 English. Use common words, active voice, short sentences, and one idea per sentence. Keep required Junior terms from the root `TERMINOLOGY.md`. Explain a required term the first time a new reader may see it. Remove other jargon. + +Lead with what the reader must do or decide. Keep examples small and runnable. Add the target file name to a code block when the code belongs in a file. Prefer: @@ -52,8 +54,8 @@ Prefer: Avoid: -- internal implementation chatter before the user-facing outcome -- stale migration details unless a redirect or compatibility note needs them +- internal design details before the user-facing result +- old migration details unless a redirect or support note needs them - multiple pages competing to explain the same setup step - long inline commands that wrap poorly @@ -64,7 +66,8 @@ When adding or moving a page: 1. Add it to `packages/docs/astro.config.mjs` if it should be discoverable. 2. Add redirects for old public routes. 3. Update related pages and package README links. -4. Run `pnpm docs:check`. +4. Check each changed sentence against the writing rules above. +5. Run `pnpm docs:check`. Docs that describe plugins must keep package lists aligned with the real `@sentry/junior-*` packages and release docs. diff --git a/packages/docs/src/content/docs/contribute/local-agent-validation.md b/packages/docs/src/content/docs/contribute/local-agent-validation.md index 7dc01bcbf..ebe7d6f5c 100644 --- a/packages/docs/src/content/docs/contribute/local-agent-validation.md +++ b/packages/docs/src/content/docs/contribute/local-agent-validation.md @@ -12,15 +12,14 @@ related: - /start-here/verify-and-troubleshoot/ --- -Use this runbook for product, runtime, prompt, skill, plugin, tool, sandbox, or -environment-backed credential changes that are not specifically about Slack -ingress, Slack message formatting, Slack retries, or Slack OAuth UI. The local -agent should be the first manual behavior check for those changes. +Use this runbook for changes to the product, runtime, prompts, skills, plugins, +tools, sandbox, or credentials. Do not use it first for Slack input, message +format, retries, or OAuth screens. For all other changes, test the local agent +first. -Inside this monorepo, `pnpm cli -- ...` runs Junior from `apps/example`. Treat -that app as the canonical local validation app: it loads the example SOUL, -WORLD, local skills, plugin-bundled skills, and normal development env without -requiring Slack. +In this monorepo, `pnpm cli -- ...` runs Junior from `apps/example`. Use this +app for local tests. It loads the example SOUL, WORLD, local skills, plugin +skills, and normal development environment. It does not require Slack. ## First Check @@ -52,8 +51,8 @@ The command should print a Junior response and exit with status `0`. If it reports missing model or provider credentials, refresh or add the required environment variables and rerun the same prompt. -`-p` uses a fresh local conversation for each invocation. Use interactive mode -when you need to validate multi-turn context. +`-p` uses a new local conversation for each command. Use interactive mode to +test context across turns. ## Example App Checks diff --git a/packages/docs/src/content/docs/extend/_plugin-template.md b/packages/docs/src/content/docs/extend/_plugin-template.md index 065d884ec..d0aed3d9d 100644 --- a/packages/docs/src/content/docs/extend/_plugin-template.md +++ b/packages/docs/src/content/docs/extend/_plugin-template.md @@ -1,6 +1,6 @@ --- title: Plugin Page Template -description: Canonical structure for plugin setup pages. +description: Required structure for plugin setup pages. type: tutorial prerequisites: - /extend/ @@ -10,7 +10,7 @@ related: - /reference/config-and-env/ --- -Use this template for plugin setup pages so every plugin guide follows the same reader path. +Use this template for plugin setup pages. Follow the writing rules in [Documentation Guidelines](/contribute/documentation-guidelines/). Give every plugin guide the same reader path. ## Install @@ -30,7 +30,7 @@ import { defineJuniorPlugins } from "@sentry/junior"; export const plugins = defineJuniorPlugins(["@sentry/junior-example"]); ``` -Plugins that require runtime hooks — tool registration, session processing, Git hooks, or other host-side behavior — use a JavaScript factory that returns a `defineJuniorPlugin(...)` registration. Register those with an explicit factory call: +Some plugins need runtime hooks. These hooks can register tools, process sessions, or run Git actions. Such plugins use a JavaScript factory that returns a `defineJuniorPlugin(...)` registration. Register them with an explicit factory call: ```ts title="plugins.ts" import { defineJuniorPlugins } from "@sentry/junior"; @@ -43,7 +43,7 @@ Name a runtime plugin factory `Plugin`, export it as a function, and call it even when it has no options. Do not document a `createPlugin` alias or a prebuilt plugin registration. -Do not register a factory-based plugin as a bare package-name string. A bare string does not run runtime hooks, so the plugin will not activate its runtime behavior. Check the plugin package's README or setup page to confirm which registration style it requires. +Do not register a factory-based plugin as a bare package-name string. A bare string does not run runtime hooks. Check the plugin README or setup page to find the required registration style. ## Config diff --git a/packages/docs/src/content/docs/extend/build-a-plugin.md b/packages/docs/src/content/docs/extend/build-a-plugin.md index 7012c5645..4de23bb96 100644 --- a/packages/docs/src/content/docs/extend/build-a-plugin.md +++ b/packages/docs/src/content/docs/extend/build-a-plugin.md @@ -178,23 +178,23 @@ export const plugins = defineJuniorPlugins([myProviderPlugin()]); Use `ctx.decision.replaceInput(...)` only with object-shaped tool input. Junior rejects non-object replacements before the tool runs. -### Runtime surfaces +### Runtime hooks Use the smallest surface that matches the deterministic boundary your plugin needs: -| Surface | Purpose | -| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sandboxPrepare(ctx)` | Prepare files or runtime state inside a sandbox before agent tools run. | -| `beforeToolExecute(ctx)` | Deny or rewrite object-shaped tool input and set non-secret env values before a tool runs. | -| `afterMcpTool(ctx)` | Run junior-owned side effects after a successful hosted MCP tool call. Prefer this for conversation annotations instead of inventing a parallel tool contract. | -| `tools(ctx)` | Return host-registered tool definitions for the current turn. Tool names must be plugin-local camelCase names. | -| `heartbeat(ctx)` | Run bounded periodic work from Junior's internal heartbeat route. | -| `apiRoutes(ctx)` | Return a Hono or fetch-compatible app mounted under `/api/plugins/:pluginName/*` with auth already applied. Use `ctx.users.resolve(email)` only when the route needs canonical personal ownership. | -| `tasks` | Register plugin-owned background tasks. V1 tasks run after completed sessions and load bounded run context with `ctx.run.load()`. | +| Surface | Purpose | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sandboxPrepare(ctx)` | Prepare files or runtime state inside a sandbox before agent tools run. | +| `beforeToolExecute(ctx)` | Deny or rewrite object-shaped tool input and set non-secret env values before a tool runs. | +| `afterMcpTool(ctx)` | Run junior-owned side effects after a successful hosted MCP tool call. Prefer this for conversation annotations instead of inventing a parallel tool contract. | +| `tools(ctx)` | Return host-registered tool definitions for the current turn. Tool names must be plugin-local camelCase names. | +| `heartbeat(ctx)` | Run bounded periodic work from Junior's internal heartbeat route. | +| `apiRoutes(ctx)` | Return a Hono or fetch-compatible app mounted under `/api/plugins/:pluginName/*` with auth already applied. Use `ctx.users.resolve(email)` only when the route must link work to one person. | +| `tasks` | Register plugin-owned background tasks. V1 tasks run after completed sessions and load bounded run context with `ctx.run.load()`. | `tools(ctx)` receives the active turn context, `ctx.state`, and `ctx.log`. Call -`ctx.users.resolveActor()` only when a tool needs the active actor's canonical -identity or linked user. Return tool definitions keyed by the plugin-local tool +`ctx.users.resolveActor()` only when a tool needs the active actor's linked +identity or user. Return tool definitions keyed by the plugin-local tool names your plugin owns. Junior exposes them to the agent as `_`, where `pluginNamespace` is derived from the plugin manifest name. For example, @@ -253,8 +253,8 @@ model-repairable failures; Junior projects successful values and thrown errors onto the agent runtime's separate result channels. Use `approvalMode: "auto"` when Junior should review an action according to its -annotations and source. Use `review` when every invocation requires review, or -`approve` only when the tool is safe to execute without review. Omitting the +annotations and source. Use `review` when every tool call requires review. Use +`approve` only when the tool is safe to run without review. Omitting the field leaves the tool outside action review. Annotations describe side effects; they do not authorize an action. Junior diff --git a/packages/docs/src/content/docs/extend/index.md b/packages/docs/src/content/docs/extend/index.md index b9871a8e0..59eedae50 100644 --- a/packages/docs/src/content/docs/extend/index.md +++ b/packages/docs/src/content/docs/extend/index.md @@ -12,9 +12,10 @@ related: --- Plugins add provider manifests, credentials, tools, runtime hooks, background -work, and optional skills. Start with a packaged plugin when one exists; build a -custom plugin only when the app needs a new provider or deterministic runtime -behavior. +work, and optional skills. A manifest is a file that describes a plugin. A +runtime hook lets the plugin run code in the Junior app. Use a packaged plugin +when one exists. Build a custom plugin only when the app needs a new provider or +fixed behavior that code must control. ## Choose a plugin @@ -82,9 +83,9 @@ import { plugins } from "./plugins.ts"; export default await createApp({ plugins }); ``` -Manifest-only plugins may be registered by package name. Plugins with runtime -hooks export a JavaScript factory. Each provider page documents its required -registration and environment variables. +You can register a manifest-only plugin by package name. Plugins with runtime +hooks export a JavaScript function. Each provider page lists the required setup +and environment variables. ## Add an app-local plugin @@ -98,8 +99,8 @@ app/plugins// └── SKILL.md ``` -Use this shape for app-specific provider configuration or workflows that do not -need backend hooks. Runtime hooks and host tools require a code plugin; follow +Use this layout for app-specific provider settings or work that does not need +server hooks. Runtime hooks and host tools require a code plugin. Follow [Build a Plugin](/extend/build-a-plugin/). ## Validate diff --git a/packages/docs/src/content/docs/extend/vercel-plugin.md b/packages/docs/src/content/docs/extend/vercel-plugin.md index 392122750..d23b59a0c 100644 --- a/packages/docs/src/content/docs/extend/vercel-plugin.md +++ b/packages/docs/src/content/docs/extend/vercel-plugin.md @@ -119,10 +119,10 @@ Set `VERCEL_WEBHOOK_SECRET` to enable resource subscriptions. See [Resource Subscriptions](/concepts/resource-subscriptions/) for the difference between temporary subscriptions and durable event tasks. -Deployment watches match Vercel's canonical `prj_...` project ID. Users can name -a project or supply its ID; Junior resolves the canonical ID through Vercel's -authenticated project API. Include the team slug or ID when projects with the -same name may exist in more than one account. +Deployment watches use Vercel's `prj_...` project ID. Users can give a project +name or ID. Junior gets the project ID from Vercel's authenticated project API. +Include the team slug or ID when projects with the same name may exist in more +than one account. ### `deployment` diff --git a/packages/docs/src/content/docs/reference/config-and-env.md b/packages/docs/src/content/docs/reference/config-and-env.md index 15f97632d..29efb3f9b 100644 --- a/packages/docs/src/content/docs/reference/config-and-env.md +++ b/packages/docs/src/content/docs/reference/config-and-env.md @@ -21,7 +21,7 @@ related: | `DATABASE_URL` | Yes | Standard Neon/Vercel Postgres URL for Junior SQL records and reporting. | | `JUNIOR_DATABASE_DRIVER` | No | SQL client driver for Junior records: `neon` or `postgres`. Defaults to `neon`; set `postgres` for local Postgres or node-postgres deployments. | | `JUNIOR_SQL_STATEMENT_TIMEOUT_MS` | No | PostgreSQL runtime statement timeout in milliseconds. Defaults to `30000` (30 seconds); set `0` to disable. This does not limit `junior upgrade` migrations. | -| `JUNIOR_CONVERSATION_WORK_ENABLED` | No | Operational kill switch for queue processing and heartbeat recovery. Defaults to `true`; set `false` to acknowledge wakes without running or recovering conversation work. | +| `JUNIOR_CONVERSATION_WORK_ENABLED` | No | Operational kill switch for queue processing and heartbeat recovery. Defaults to `true`; set `false` to acknowledge wakes without running or recovering conversation work. | | `JUNIOR_SECRET` | Yes | Signs internal queue/callback payloads and sandbox egress actor context. | | `JUNIOR_BOT_NAME` | No | Bot display/config naming. | | `JUNIOR_SLASH_COMMAND` | No | Slack slash command for account-management flows. Defaults to `/jr`; the Slack app command must match this value. | @@ -37,11 +37,11 @@ related: | `AI_WEB_SEARCH_MODEL` | No | Override for the `webSearch` tool model. Defaults to `openai/gpt-5.4`; does not fall through to `AI_MODEL`. | | `SANDBOX_VCPUS` | No | Legacy fallback for sandbox vCPUs and the build-time snapshot command. Prefer `createApp({ sandbox: { vcpus } })` for runtime sandboxes. Each vCPU provides 2 GB of memory. | | `VERCEL_SANDBOX_KEEPALIVE_MS` | No | Extends an active sandbox by this duration on each tool acquire. Disabled when unset or `0`; `900000` (15 minutes) is recommended for production Vercel deployments. | -| `JUNIOR_BASE_URL` | No | Canonical base URL for callback/auth URL generation. | +| `JUNIOR_BASE_URL` | No | Main base URL for callback and authorization URLs. | | `JUNIOR_STATE_KEY_PREFIX` | No | Optional namespace prepended to all state-adapter keys, locks, and queues. Use separate prefixes when sharing one Redis database across environments. | | `CRON_SECRET` or `JUNIOR_SCHEDULER_SECRET` | Conditional | Bearer token for the internal heartbeat route; use `CRON_SECRET` with Vercel Cron, or `JUNIOR_SCHEDULER_SECRET` for a non-Vercel heartbeat caller. | | `JUNIOR_TIMEZONE` | No | Default IANA timezone for scheduler authoring when the scheduler plugin is enabled. Defaults to `America/Los_Angeles`. | -| `AI_GATEWAY_API_KEY` | No | Fallback AI Gateway auth when Vercel OIDC is unavailable (local/CI/non-Vercel hosts). On Vercel, prefer project OIDC so usage attributes to the project. | +| `AI_GATEWAY_API_KEY` | No | Fallback AI Gateway auth when Vercel OIDC is unavailable (local/CI/non-Vercel hosts). On Vercel, prefer project OIDC so usage attributes to the project. | Junior applies `JUNIOR_SQL_STATEMENT_TIMEOUT_MS` through PostgreSQL `statement_timeout` for both the Neon and node-postgres drivers. `junior upgrade` does not apply this runtime limit because schema migrations can legitimately take longer. diff --git a/packages/docs/src/content/docs/start-here/deploy-to-vercel.md b/packages/docs/src/content/docs/start-here/deploy-to-vercel.md index f7c0d0336..55c4f1f43 100644 --- a/packages/docs/src/content/docs/start-here/deploy-to-vercel.md +++ b/packages/docs/src/content/docs/start-here/deploy-to-vercel.md @@ -60,8 +60,8 @@ Run database migrations before the app build: pnpm exec junior upgrade && pnpm build ``` -`junior upgrade` applies the idempotent core and plugin SQL migrations, while -`junior snapshot create` inside `pnpm build` prepares sandbox runtime +`junior upgrade` applies each core and plugin SQL migration only once. The +`junior snapshot create` command inside `pnpm build` prepares the sandbox dependencies declared by enabled plugins. Existing pre-Drizzle deployments must complete the bridge-release procedure below before this build command can succeed. @@ -101,20 +101,20 @@ The heartbeat endpoint returns `401` unless the incoming Vercel Cron request has Set the core runtime variables in Vercel: -| Variable | Required | Purpose | -| ------------------------------------------- | ----------- | ------------------------------------------------------------------------------ | -| `SLACK_SIGNING_SECRET` | Yes | Verifies Slack requests. | -| `SLACK_BOT_TOKEN` or `SLACK_BOT_USER_TOKEN` | Yes | Posts replies and calls Slack APIs. | -| `REDIS_URL` | Yes | Queue and runtime state storage. | -| `DATABASE_URL` | Yes | Standard Neon/Vercel Postgres URL for Junior SQL records and reporting. | -| `JUNIOR_DATABASE_DRIVER` | No | SQL client driver: `neon` or `postgres`. Defaults to `neon`. | -| `JUNIOR_SQL_STATEMENT_TIMEOUT_MS` | No | Runtime PostgreSQL statement timeout. Defaults to `30000`; set `0` to disable. | -| `JUNIOR_SECRET` | Yes | Signs internal callbacks and sandbox actor context. | -| `CRON_SECRET` | Yes | Authenticates Vercel Cron requests to the internal heartbeat route. | -| `JUNIOR_BASE_URL` | Conditional | Canonical URL for OAuth and callback URLs when Vercel URL envs are not enough. | -| `JUNIOR_STATE_KEY_PREFIX` | No | Redis key namespace for this deployment when sharing one Redis database. | +| Variable | Required | Purpose | +| ------------------------------------------- | ----------- | --------------------------------------------------------------------------------- | +| `SLACK_SIGNING_SECRET` | Yes | Verifies Slack requests. | +| `SLACK_BOT_TOKEN` or `SLACK_BOT_USER_TOKEN` | Yes | Posts replies and calls Slack APIs. | +| `REDIS_URL` | Yes | Queue and runtime state storage. | +| `DATABASE_URL` | Yes | Standard Neon/Vercel Postgres URL for Junior SQL records and reporting. | +| `JUNIOR_DATABASE_DRIVER` | No | SQL client driver: `neon` or `postgres`. Defaults to `neon`. | +| `JUNIOR_SQL_STATEMENT_TIMEOUT_MS` | No | Runtime PostgreSQL statement timeout. Defaults to `30000`; set `0` to disable. | +| `JUNIOR_SECRET` | Yes | Signs internal callbacks and sandbox actor context. | +| `CRON_SECRET` | Yes | Authenticates Vercel Cron requests to the internal heartbeat route. | +| `JUNIOR_BASE_URL` | Conditional | Main URL for OAuth and callback URLs when Vercel URL values are not enough. | +| `JUNIOR_STATE_KEY_PREFIX` | No | Redis key namespace for this deployment when sharing one Redis database. | | `AI_GATEWAY_API_KEY` | Optional | Fallback AI Gateway auth when OIDC is unavailable. Prefer project OIDC on Vercel. | -| `VERCEL_SANDBOX_KEEPALIVE_MS` | Recommended | Extends an active sandbox on each tool acquire. Set to `900000` (15 minutes). | +| `VERCEL_SANDBOX_KEEPALIVE_MS` | Recommended | Extends an active sandbox on each tool acquire. Set to `900000` (15 minutes). | ### AI Gateway auth (preferred: project OIDC) @@ -126,7 +126,7 @@ usage and spend attribute to this project instead of showing as `unknown`. 2. Do **not** set `AI_GATEWAY_API_KEY` in production unless you need a non-OIDC fallback. When both are present, Junior prefers OIDC. 3. For local development without OIDC, either run `vercel link` + `vercel env - pull` or set `AI_GATEWAY_API_KEY`. +pull` or set `AI_GATEWAY_API_KEY`. `AI_GATEWAY_API_KEY` remains supported for CI and non-Vercel hosts. Team-scoped keys without a `projectId` will still show as `unknown` in the AI Gateway diff --git a/packages/docs/src/content/docs/start-here/overview.md b/packages/docs/src/content/docs/start-here/overview.md index 2cb98cdda..9186ebe57 100644 --- a/packages/docs/src/content/docs/start-here/overview.md +++ b/packages/docs/src/content/docs/start-here/overview.md @@ -12,11 +12,11 @@ related: - /extend/ --- -Junior is a Slack bot runtime for teams that want company tools available from Slack threads. A Junior app receives Slack events, runs agent turns with configured tools and skills, and posts finalized replies back to the originating thread. +Junior is a Slack bot for teams that want to use company tools from Slack threads. A Junior app receives Slack events and runs turns with its tools and skills. It posts final replies to the original thread. -## Runtime Shape +## Main parts -Junior apps are small Hono apps built and deployed with Nitro. `createApp()` owns the public runtime routes, while `juniorNitro()` makes app files and declared plugin packages available in the deployment bundle. +Junior apps are small Hono apps that use Nitro to build and deploy. `createApp()` owns the public routes. `juniorNitro()` adds app files and declared plugin packages to the deployed app. | Layer | What it controls | | ---------- | ---------------------------------------------------------------------------------------- | @@ -42,7 +42,7 @@ The recommended first app path is `junior init`, then Slack setup, then Vercel d ## What to Configure First -Configure only the core runtime before adding provider plugins. That keeps early failures narrow: health route, Slack webhook, queue callback, and one thread reply. +Set up only the core app before you add provider plugins. This limits early failures to the health route, Slack webhook, queue callback, and one thread reply. After that baseline works, add one plugin at a time. Each plugin page lists its env vars, auth model, verification request, and failure modes. diff --git a/policies/README.md b/policies/README.md index cdfb34be3..c3c1af5ac 100644 --- a/policies/README.md +++ b/policies/README.md @@ -9,7 +9,7 @@ error handling, provider boundaries, interface design, and serverless work. Do not use policies for: -- one feature's architecture or lifecycle +- one feature's design or state changes - plans, status notes, TODOs, or rollout tracking - copied schemas, commands, or test inventories - public product docs diff --git a/policies/testing.md b/policies/testing.md index 92a53b848..d1c465397 100644 --- a/policies/testing.md +++ b/policies/testing.md @@ -2,7 +2,7 @@ ## Intent -Tests should protect product contracts without freezing implementation details. +Tests should protect product contracts. They should not prevent safe changes to internal code. Prefer higher-fidelity behavior coverage when it is stable enough. Routine refactors should not churn brittle unit tests.