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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions packages/docs/src/content/docs/cli/_cli-template.md
Original file line number Diff line number Diff line change
@@ -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/
Expand All @@ -10,23 +10,23 @@ 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

Add optional path, subcommand, or flag examples only when they change how someone runs the command.

## 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

Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/content/docs/cli/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -34,13 +34,13 @@ pnpm exec junior chat -p "Summarize this repository"
| -------------- | -------------------------------------------------- |
| `-p <message>` | 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.

Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/content/docs/concepts/execution-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:

Expand All @@ -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

Expand All @@ -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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions packages/docs/src/content/docs/extend/_plugin-template.md
Original file line number Diff line number Diff line change
@@ -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/
Expand All @@ -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

Expand All @@ -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";
Expand All @@ -43,7 +43,7 @@ Name a runtime plugin factory `<domain>Plugin`, export it as a function, and
call it even when it has no options. Do not document a `create<Domain>Plugin`
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

Expand Down
28 changes: 14 additions & 14 deletions packages/docs/src/content/docs/extend/build-a-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<pluginNamespace>_<toolName>`, where
`pluginNamespace` is derived from the plugin manifest name. For example,
Expand Down Expand Up @@ -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
Expand Down
17 changes: 9 additions & 8 deletions packages/docs/src/content/docs/extend/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -98,8 +99,8 @@ app/plugins/<plugin-name>/
└── 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
Expand Down
Loading
Loading