From b05118be07d7e9bc904eba18157c9d4720be230f Mon Sep 17 00:00:00 2001 From: Vivek Yanamadula Date: Wed, 29 Jul 2026 17:38:39 -0400 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=9D=20Refresh=20Rudder=20runtime?= =?UTF-8?q?=20and=20release=20knowledge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Codex Agent --- .../automation/contributor-automation.md | 2 +- .../release/release-automation.md | 10 +++--- almanac/architecture/runtime/local-state.md | 17 ++++++---- .../runtime/prompt-branch-store.md | 23 +++++++------ .../runtime/rudder-skill-runtime.md | 29 +++++++++++++---- almanac/architecture/runtime/telemetry.md | 12 +++++-- .../architecture/tooling/package-baseline.md | 4 +-- .../architecture/tooling/plugin-package.md | 6 ++-- .../product/intent-driven-test-generation.md | 16 +++++----- .../concepts/product/test-intent-standards.md | 25 ++++++++------- almanac/concepts/runtime/prompt-history.md | 14 ++++---- .../database/generated-drizzle-migrations.md | 9 ++++-- .../decisions/product/byok-skill-workflow.md | 14 ++++---- .../artifact-checked-plugin-publishing.md | 6 ++-- almanac/getting-started.md | 12 +++---- .../change-shared-infrastructure.md | 13 +++----- .../guides/release/prepare-package-release.md | 4 +-- almanac/guides/runtime/use-prompt-capture.md | 12 +++---- .../reference/automation/github-workflows.md | 8 ++--- .../configuration/environment-variables.md | 32 +++++++++---------- .../reference/contributor/protected-paths.md | 5 ++- .../database/prompt-branches-schema.md | 17 +++++----- almanac/reference/tooling/package-scripts.md | 2 +- almanac/reference/tooling/typescript-build.md | 6 ++-- 24 files changed, 165 insertions(+), 133 deletions(-) diff --git a/almanac/architecture/automation/contributor-automation.md b/almanac/architecture/automation/contributor-automation.md index 8eaa8ce..c005bbd 100644 --- a/almanac/architecture/automation/contributor-automation.md +++ b/almanac/architecture/automation/contributor-automation.md @@ -48,6 +48,6 @@ That remediation flow has its own validation boundary. If it applies any fixes, ## Agent Guards -`dangerfile.ts` protects `README.md`, `LICENSE`, `CLAUDE.md`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` from agent-authored pull request changes [@dangerfile]. It detects agent authorship from the PR author, commit author names and emails, and `Co-authored-by` trailers [@dangerfile]. The Danger workflow runs `npm run danger:ci` on pull requests to `main` after installing dependencies on Node 24 [@danger-workflow] [@package]. +`dangerfile.ts` protects `README.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `CLAUDE.md`, `docs/**`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` from agent-authored pull request changes [@dangerfile]. It detects agent authorship from the PR author, commit author names and emails, and `Co-authored-by` trailers [@dangerfile]. The Danger workflow runs `npm run danger:ci` on pull requests to `main` after installing dependencies on Node 24 [@danger-workflow] [@package]. For detected-agent pull requests, Danger fails any changed path matching `PROTECTED_PATHS` and warns when the policy files `dangerfile.ts` or `.github/workflows/danger.yml` change [@dangerfile]. It also enforces inline `agent-guard:off` and `agent-guard:on` regions: invalid marker nesting fails, agent-authored changes inside protected regions fail, and marker changes warn for explicit review [@dangerfile]. The lookup version of this contract belongs in [Protected Paths](../../reference/contributor/protected-paths). diff --git a/almanac/architecture/release/release-automation.md b/almanac/architecture/release/release-automation.md index b4d623e..24205ee 100644 --- a/almanac/architecture/release/release-automation.md +++ b/almanac/architecture/release/release-automation.md @@ -18,23 +18,23 @@ Rudder's release automation is split between a publishing workflow on `main` and ## Version As Release Input -`package.json` is the only version input for the workflows. The package is currently `@ruddercode/rudder-plugin` at version `0.1.0`, and both workflows turn that version into tag `rudder-plugin-v0.1.0` at runtime [@package-json] [@publish-workflow] [@release-alert]. The release-alert workflow performs the same package-name, version, tag, npm, and GitHub Release checks on pull requests to `main` [@release-alert]. +`package.json` is the only version input for the workflows. The package is currently `@ruddercode/rudder-plugin` at version `0.1.3`, and both workflows turn that version into tag `rudder-plugin-v0.1.3` at runtime [@package-json] [@publish-workflow] [@release-alert]. The release-alert workflow performs the same package-name, version, tag, npm, and GitHub Release checks on pull requests to `main` [@release-alert]. Both workflows reject any package name other than `@ruddercode/rudder-plugin` before attempting release work [@publish-workflow] [@release-alert]. This is a release invariant: changing the package name affects plugin marketplace metadata, npm publication, and tag naming, so evaluate it through [Prepare Package Release](../../guides/release/prepare-package-release) and [Rudder Plugin Package](../tooling/plugin-package). ## Publish Job -The publish workflow runs on pushes to `main` and on manual dispatch, with a single `publish-rudder-plugin` concurrency group and `contents: write` plus `id-token: write` permissions [@publish-workflow]. Its first shell step checks whether npmjs.org already has `name@version`, whether the package exists at all, whether the `rudder-plugin-v` tag exists, and whether a GitHub Release exists for that tag [@publish-workflow]. +The publish workflow runs on pushes to `main` and on manual dispatch, with a single `publish-rudder-plugin` concurrency group and `contents: write` plus `id-token: write` permissions [@publish-workflow]. Its first shell step checks whether npmjs.org already has `name@version`, whether the `rudder-plugin-v` tag exists, and whether a GitHub Release exists for that tag [@publish-workflow]. -Those checks create separate flags for each artifact. A missing npmjs.org version enables npm publishing, a missing package plus missing version marks a bootstrap publish, a missing tag enables tag creation, and a missing GitHub Release enables release creation [@publish-workflow]. When any artifact is missing, the job upgrades npm, installs dependencies with `npm ci`, validates the plugin package, publishes to npmjs.org when needed, pushes the plugin tag when needed, and creates the GitHub Release with generated notes when needed [@publish-workflow]. +Those checks create separate flags for each artifact. A missing npmjs.org version enables npm publishing, a missing tag enables tag creation, and a missing GitHub Release enables release creation [@publish-workflow]. When any artifact is missing, the job upgrades npm, installs dependencies with `npm ci`, writes release telemetry defaults into `src/telemetry-build-config.ts`, validates the plugin package with `DO_NOT_TRACK=1`, publishes to npmjs.org when needed with Trusted Publishing, pushes the plugin tag when needed, and creates the GitHub Release with generated notes when needed [@publish-workflow]. -The package scripts are part of that path because the publish workflow validates with `npm run check:agent-layout`, `npm run typecheck`, `npm test`, `npm run build`, and `npm pack --dry-run`, while `npm publish` also uses the package lifecycle in `package.json` [@publish-workflow] [@package-json]. The exact scripts are listed in [Package Scripts](../../reference/tooling/package-scripts). +The package scripts are part of that path because the publish workflow validates with `npm run check:agent-layout`, `npm run typecheck`, `npm test`, `npm run build`, and `npm pack --dry-run`, while `npm publish` also uses the package lifecycle in `package.json` [@publish-workflow] [@package-json]. The GitHub Release title is `Rudder v` even though the tag remains `rudder-plugin-v` [@publish-workflow]. The exact scripts are listed in [Package Scripts](../../reference/tooling/package-scripts). ## Release Alert Job The release-alert workflow runs on pull requests opened, synchronized, or reopened against `main`; it has read permissions for contents plus write permission for pull request comments [@release-alert]. It uses a per-PR `plugin-release-alert-` concurrency group and cancels in-progress runs on newer pushes, so the latest branch state owns the PR warning [@release-alert]. -The alert job mirrors the publish checks without publishing. It checks npmjs.org, bootstrap-token need, tag creation, and GitHub Release creation, then sets `will_release=true` when any release artifact would be created after merge [@release-alert]. A GitHub Script step searches for an existing comment containing `` and updates it, or creates one when missing [@release-alert]. The comment warns when merge would publish the plugin, use the bootstrap token, create the plugin tag, or create a release, and it switches to a no-release message when all plugin artifacts already exist for the version [@release-alert]. +The alert job mirrors the publish checks without publishing. It checks npmjs.org, tag creation, and GitHub Release creation, then sets `will_release=true` when any release artifact would be created after merge [@release-alert]. A GitHub Script step searches for an existing comment containing `` and updates it, or creates one when missing [@release-alert]. The comment warns when merge would publish the plugin, create the plugin tag, or create a release, and it switches to a no-release message when all plugin artifacts already exist for the version [@release-alert]. ## Release Model diff --git a/almanac/architecture/runtime/local-state.md b/almanac/architecture/runtime/local-state.md index 90ef3da..27ddf16 100644 --- a/almanac/architecture/runtime/local-state.md +++ b/almanac/architecture/runtime/local-state.md @@ -1,27 +1,30 @@ --- title: "Local State" -summary: "Rudder keeps runtime state in a user-scoped home directory that owns the SQLite database, prompt-capture preference, telemetry identity file, and dashboard port defaults." +summary: "Rudder keeps runtime state in a user-scoped home directory that owns the SQLite database, telemetry identity, update-check cache, backups, and dashboard port defaults." topics: [architecture, runtime, local-state, sqlite, prompt-capture] sources: - id: db-client type: file path: src/db/client.ts - - id: prompt-control - type: file - path: src/prompt-control.ts - id: telemetry type: file path: src/telemetry.ts + - id: update-script + type: file + path: skills/rudder/scripts/update.mjs + - id: backup-script + type: file + path: skills/rudder/scripts/backup-tests.mjs - id: gitignore type: file path: .gitignore --- -Rudder local state is the small persistent runtime surface that exists outside the source tree. The database client resolves a Rudder home directory from `RUDDER_HOME` or `~/.rudder`, stores the SQLite database at `rudder.db`, opens that database through a process-wide singleton, enables WAL journaling, applies generated Drizzle migrations, and then exposes Drizzle access [@db-client]. The same home directory stores the prompt-capture disable marker and anonymous telemetry identity file, so [Prompt Branch Store](prompt-branch-store), prompt controls, and [Telemetry](telemetry) share one local state root [@prompt-control] [@telemetry]. Runtime artifacts live under the selected Rudder home instead of a repository-local state directory, while the source tree keeps only the code and configuration that derive those paths [@db-client] [@gitignore]. +Rudder local state is the small persistent runtime surface that exists outside the source tree. The database client resolves a Rudder home directory from `RUDDER_HOME` or `~/.rudder`, stores the SQLite database at `rudder.db`, opens that database through a process-wide singleton, enables WAL journaling, applies generated Drizzle migrations, and then exposes Drizzle access [@db-client]. The same home directory stores the anonymous telemetry identity file, the update-check cache, and skill-created test-reset backups, so [Prompt Branch Store](prompt-branch-store), [Telemetry](telemetry), and the skill runtime share one local state root [@telemetry] [@update-script] [@backup-script]. Runtime artifacts live under the selected Rudder home instead of a repository-local state directory, while the source tree keeps only the code and configuration that derive those paths [@db-client] [@gitignore]. ## State Root -`rudderHome()` is the owner of the local state path. It returns `process.env.RUDDER_HOME` when that value is present, and otherwise joins the operating-system home directory with `.rudder` [@db-client]. `dbPath()` derives the database location by joining that root with `rudder.db`, and `promptCaptureDisabledPath()` derives the persistent capture preference as `/prompt-capture-disabled` [@db-client] [@prompt-control]. +`rudderHome()` is the owner of the local state path. It returns `process.env.RUDDER_HOME` when that value is present, and otherwise joins the operating-system home directory with `.rudder` [@db-client]. `dbPath()` derives the database location by joining that root with `rudder.db` [@db-client]. The update helper derives `/update-state.json`, and the backup helper writes test-reset backups under `/backups/` [@update-script] [@backup-script]. The source tree does not carry a repo-local state directory convention. The repository ignore file covers dependencies, build output, generated backups, logs, environment files, coverage, and editor files, but it does not define a `.rudder/` workspace cache [@gitignore]. The runtime code instead creates the selected Rudder home directory directly, so changing the state location is an environment-variable choice rather than a working-tree layout change [@db-client]. @@ -37,4 +40,4 @@ Migration application is deliberately part of the open flow. `openDb()` derives ## Shared Boundary -Local state currently covers the SQLite database path, the prompt-capture preference marker, the telemetry identity file, and the dashboard port default. Telemetry builds `identity.json` under `rudderHome()`, reads an existing `{ id }` value when present, and writes a generated UUID there on a best-effort basis when it needs a new anonymous installation identity [@telemetry]. The important invariant is that runtime code should derive persistent paths from `rudderHome()` instead of inventing new repository-local locations. That keeps [Telemetry](telemetry), [Prompt Branch Store](prompt-branch-store), prompt controls, and the environment-variable reference aligned around the same state root [@db-client] [@prompt-control]. +Local state currently covers the SQLite database path, the telemetry identity file, the update-check cache, skill backup directories, and the dashboard port default. Telemetry builds `identity.json` under `rudderHome()`, reads an existing `{ id }` value when present, and writes a generated UUID there on a best-effort basis when it needs a new anonymous installation identity [@telemetry]. The update helper writes `update-state.json` atomically through a temporary file with mode `0600` after creating the Rudder home with mode `0700` [@update-script]. The important invariant is that runtime code should derive persistent paths from `rudderHome()` instead of inventing new repository-local locations. That keeps [Telemetry](telemetry), [Prompt Branch Store](prompt-branch-store), the update helper, and the environment-variable reference aligned around the same state root [@db-client] [@telemetry] [@update-script]. diff --git a/almanac/architecture/runtime/prompt-branch-store.md b/almanac/architecture/runtime/prompt-branch-store.md index 9943648..48caf94 100644 --- a/almanac/architecture/runtime/prompt-branch-store.md +++ b/almanac/architecture/runtime/prompt-branch-store.md @@ -1,6 +1,6 @@ --- title: "Prompt Branch Store" -summary: "The prompt branch store records captured prompt text and reconciles each prompt to the normalized Git branch active after its agent turn." +summary: "The prompt branch store records captured prompt context and reconciles each prompt to the normalized Git branch active after its agent turn." topics: [architecture, runtime, prompt-capture, prompt-history, database, sqlite] sources: - id: db-client @@ -15,15 +15,18 @@ sources: - id: prompt-hook type: file path: src/prompt-hook.ts - - id: prompt-control + - id: transcript type: file - path: src/prompt-control.ts + path: src/transcript.ts - id: git-context type: file path: src/git-context.ts - id: prompt-migration type: file path: drizzle/20260722200723_prompt-branch-links/migration.sql + - id: previous-output-migration + type: file + path: drizzle/20260723191552_capture-previous-agent-output/migration.sql - id: prompt-tests type: file path: test/prompt-tagger.test.ts @@ -37,26 +40,26 @@ sources: # Prompt Branch Store -The prompt branch store is Rudder's implemented local intent store. It records submitted prompt text together with agent source, session ID, prompt ID, normalized repository, normalized branch, submission time, and optional reconciliation time in `prompt_branches` [@schema] [@prompt-tagger]. The store exists so the installed [Rudder plugin package](../tooling/plugin-package) and [Rudder skill runtime](rudder-skill-runtime) can give the current coding agent branch-specific prompt context for [Prompt History](../../concepts/runtime/prompt-history) without calling a separate model service [@prompt-hook] [@skill-tests]. +The prompt branch store is Rudder's implemented local intent store. It records submitted prompt text together with optional previous agent output, agent source, session ID, prompt ID, normalized repository, normalized branch, submission time, and optional reconciliation time in `prompt_branches` [@schema] [@prompt-tagger]. The store exists so the installed [Rudder plugin package](../tooling/plugin-package) and [Rudder skill runtime](rudder-skill-runtime) can give the current coding agent branch-specific prompt context for [Prompt History](../../concepts/runtime/prompt-history) without calling a separate model service [@prompt-hook] [@skill-tests]. ## Storage Boundary The store uses the same [Local State](local-state) database path as the rest of the runtime. `openDb()` resolves `RUDDER_HOME` or `~/.rudder`, creates the state directory with mode `0700`, opens `rudder.db`, restricts the database file to mode `0600` when the filesystem supports it, enables WAL, sets a 5000 ms busy timeout, enables SQLite secure deletion, and applies committed Drizzle migrations before exposing the cached handles [@db-client]. `RUDDER_MIGRATIONS_PATH` can override the migration folder, which lets the bundled plugin hook point the migrator at `dist/drizzle` inside an installed package [@db-client]. -`src/db/schema.ts` declares only the `prompt_branches` table in the exported schema object [@schema]. The prompt migration creates that table, adds indexes for repository/branch and source/session lookups, and drops the older `session_branches` table [@prompt-migration]. The exact table contract is listed in [Prompt Branches Schema](../../reference/database/prompt-branches-schema). +`src/db/schema.ts` declares only the `prompt_branches` table in the exported schema object [@schema]. The prompt migration creates that table, adds indexes for repository/branch and source/session lookups, and drops the older `session_branches` table [@prompt-migration]. A later migration adds nullable `previous_agent_output` to the same table [@previous-output-migration]. The exact table contract is listed in [Prompt Branches Schema](../../reference/database/prompt-branches-schema). ## Hook Lifecycle -`recordPromptHookEvent(source, payload)` is the hook-facing entrypoint. It first checks `promptCaptureDisabled()`, then normalizes Claude Code, Codex, or Cursor hook payloads into a shared shape [@prompt-hook] [@prompt-control]. `UserPromptSubmit` and `beforeSubmitPrompt` events become prompt submission events, while `Stop` becomes reconciliation [@prompt-hook]. +`recordPromptHookEvent(source, payload)` is the hook-facing entrypoint. It normalizes Claude Code, Codex, or Cursor hook payloads into a shared shape [@prompt-hook]. `UserPromptSubmit` and `beforeSubmitPrompt` events become prompt submission events, while `Stop` becomes reconciliation [@prompt-hook]. The normalizer accepts optional `transcript_path`; on submit, the hook reads the latest assistant text from that JSONL transcript and passes it to the store as previous agent output when available [@prompt-hook] [@transcript]. -On submit, `recordPromptBranch()` resolves the current repository and branch, validates nonblank source/session/prompt text, generates a UUID prompt ID when the provider did not send one, and inserts the prompt row [@prompt-tagger] [@git-context]. On conflict for the same source/session/prompt ID, it updates prompt text and keeps the earliest `submitted_at` value [@prompt-tagger]. On stop, `reconcilePromptBranch()` updates the row to the branch active after the turn and fills `reconciled_at`; when no prompt ID is available, it targets the latest unreconciled prompt for that source/session pair [@prompt-tagger]. Tests cover branch movement after a prompt creates a feature branch and the fallback to the latest unreconciled prompt [@prompt-tests]. +On submit, `recordPromptBranch()` resolves the current repository and branch, validates nonblank source/session/prompt text, validates optional previous agent output, generates a UUID prompt ID when the provider did not send one, and inserts the prompt row [@prompt-tagger] [@git-context]. On conflict for the same source/session/prompt ID, it updates prompt text, keeps the earliest `submitted_at` value, and preserves the first non-null previous agent output [@prompt-tagger]. On stop, `reconcilePromptBranch()` updates the row to the branch active after the turn and fills `reconciled_at`; when no prompt ID is available, it targets the latest unreconciled prompt for that source/session pair [@prompt-tagger]. Tests cover branch movement after a prompt creates a feature branch, the fallback to the latest unreconciled prompt, and previous-output preservation across replayed submits [@prompt-tests]. -## Query And Controls +## Query And Data Controls The read paths are `promptsForSession(source, sessionId)` and `promptsForBranch(repository, branch)` [@prompt-tagger]. Session lookup orders prompts by submission time and prompt ID, while branch lookup normalizes repository and branch input before ordering by submission time, source, session ID, and prompt ID [@prompt-tagger]. -Prompt capture is optional metadata. `promptCaptureDisabled()` returns true when `RUDDER_DISABLE_PROMPT_CAPTURE` is exactly `1` or when `/prompt-capture-disabled` exists [@prompt-control]. `setPromptCaptureEnabled(false)` writes that marker, and `setPromptCaptureEnabled(true)` removes it [@prompt-control]. The skill-runtime tests verify that both the environment variable and the preference marker prevent prompt rows from being stored [@skill-tests]. +Prompt capture is optional metadata, but the current write path has no prompt-capture disable check. The skill-runtime tests leave a legacy `prompt-capture-disabled` marker in the Rudder home directory and set `RUDDER_DISABLE_PROMPT_CAPTURE=1`, then verify that `recordPromptHookEvent()` still stores the prompt [@skill-tests]. ## Failure Boundary -The hook executable must not interrupt the host agent. `bin/rudder-prompt-hook.ts` catches all errors, closes cached database handles in `finally`, and prints no output when it succeeds or when Git context is unavailable [@hook-tests]. That behavior matters because prompt-submit hook stdout can become model-visible context in host agents, so Rudder's prompt capture path is deliberately silent [@hook-tests]. +The hook executable must not interrupt the host agent. `bin/rudder-prompt-hook.ts` catches all errors, closes cached database handles in `finally`, shuts down telemetry best-effort, and prints no output when it succeeds or when Git context is unavailable [@hook-tests]. That behavior matters because prompt-submit hook stdout can become model-visible context in host agents, so Rudder's prompt capture path is deliberately silent [@hook-tests]. diff --git a/almanac/architecture/runtime/rudder-skill-runtime.md b/almanac/architecture/runtime/rudder-skill-runtime.md index c620268..5ed5001 100644 --- a/almanac/architecture/runtime/rudder-skill-runtime.md +++ b/almanac/architecture/runtime/rudder-skill-runtime.md @@ -1,6 +1,6 @@ --- title: "Rudder Skill Runtime" -summary: "The Rudder skill uses small local helper scripts for context gathering, exact-path test backups, and prompt-data controls while the host coding agent does the reasoning and test generation." +summary: "The Rudder skill uses local helper scripts for update checks, context gathering, exact-path test backups, and prompt-data deletion while the host coding agent follows the test-generation workflow." topics: [architecture, runtime, plugin, prompt-capture, test-generation-intent] sources: - id: skill @@ -15,6 +15,9 @@ sources: - id: data-script type: file path: skills/rudder/scripts/manage-data.mjs + - id: update-script + type: file + path: skills/rudder/scripts/update.mjs - id: openai-surface type: file path: skills/rudder/agents/openai.yaml @@ -25,7 +28,13 @@ sources: # Rudder Skill Runtime -The Rudder skill runtime is the local helper layer behind the installed `$rudder` workflow. `skills/rudder/SKILL.md` tells the current coding agent to derive tests from captured intent and branch changes, while three executable scripts handle deterministic context, backup, and data-control operations [@skill] [@context-script] [@backup-script] [@data-script]. This preserves the [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow): the user's current agent reasons about behavior and writes tests, while local scripts do repeatable filesystem, Git, and SQLite work [@skill]. +The Rudder skill runtime is the local helper layer behind the installed `$rudder` workflow. `skills/rudder/SKILL.md` tells the current coding agent to derive tests and minimal production changes from captured intent, while executable scripts handle update checks, deterministic context, exact-path backups, and prompt-data deletion [@skill] [@update-script] [@context-script] [@backup-script] [@data-script]. This preserves the [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow): the user's current agent reasons about behavior and writes code, while local scripts do repeatable filesystem, Git, SQLite, and plugin-update work [@skill]. + +## Update Helper + +`scripts/update.mjs` is the skill's best-effort plugin update helper. The skill runs `scripts/update.mjs check` once at the start of each test-generation invocation and continues even when the check is unavailable [@skill]. The helper reads the installed package version, queries the npm registry for the latest `@ruddercode/rudder-plugin` version with a 1500 ms timeout, caches successful checks in `/update-state.json` for 24 hours, and returns stale cached data or an unavailable result when registry lookup fails [@update-script]. + +When a user accepts an update notice, the skill runs `scripts/update.mjs apply --host ` [@skill]. The helper plans Codex updates with `codex plugin marketplace upgrade rudder --json` followed by `codex plugin add rudder@rudder --json`; Claude Code updates use `claude plugin marketplace update rudder` followed by `claude plugin update rudder@rudder` [@update-script]. Each update command is retried three times, and a failed update is reported without blocking the active Rudder flow [@update-script] [@skill-tests]. ## Context Helper @@ -33,18 +42,24 @@ The Rudder skill runtime is the local helper layer behind the installed `$rudder The skill treats this JSON as input, not as final judgment. It instructs the agent to inspect the merge base, changed paths, captured prompts, repository instructions, production diff, existing tests, and native test/coverage configuration before deciding which test changes matter [@skill]. -## Backup Helper +## Backup Helper And Test Reset `scripts/backup-tests.mjs` creates recoverable backups for explicit test paths before any reset. It requires `--cwd`, verifies the base ref, computes the merge base, requires at least one `--path`, normalizes each path to stay inside the repository, writes a binary-capable patch for tracked changes, copies listed untracked paths into the backup directory, and emits backup metadata as JSON [@backup-script]. -The skill boundary is stricter than the helper's write behavior. The skill requires the agent to show the exact tracked and untracked test paths, get explicit confirmation, run the backup helper for only those paths, verify the reported patch and untracked copies, and then restore only the confirmed test paths to the merge-base state [@skill]. It forbids `git reset --hard`, broad `git clean`, production-code changes, coverage-configuration changes, and repository-threshold changes during generation [@skill]. +The skill boundary is stricter than the helper's write behavior. The skill requires the agent to show the exact tracked and untracked test paths, inspect confirmed paths for immediately preceding Rudder source-intent tags, get explicit confirmation, run the backup helper for only those paths, verify the reported patch and untracked copies, and then restore only the confirmed test paths to the merge-base state [@skill]. After the reset, the agent attempts to restore only recorded tagged test cases plus the smallest required imports, fixtures, or helpers; untagged tests and whole-file restoration stay in the backup unless they can be isolated safely [@skill]. + +## Prompt-Backed TDD + +The skill now treats coverage as loop control rather than a source of test intent. It can generate or expand a test only when a captured user prompt or answer explicitly requires the expectation, and after the first green suite it must ask one concrete question for an uncovered behavior before writing more tests [@skill]. Each generated or rewritten test case gets a language-appropriate source-intent comment immediately above the test case in `//` form, using identifiers returned by `scripts/context.mjs` [@skill]. + +Production edits are allowed only inside a red-green cycle backed by captured intent. For each new or changed expectation, the skill writes the tagged test first, runs the narrowest test to observe the expected failure, makes the smallest production change required to satisfy that expectation, reruns the narrow test, and measures coverage only after the suite is green [@skill]. The package tests enforce that this prompt-backed production cycle replaced the older blanket instruction that generation must not change production code [@skill-tests]. ## Data Controls -`scripts/manage-data.mjs` is the skill's local privacy-control entrypoint. It reports capture status and prompt count, writes or removes the persistent `prompt-capture-disabled` marker for disable/enable, and deletes prompt rows only when invoked as `delete --confirm` [@data-script]. Confirmed deletion enables SQLite secure deletion, deletes rows from `prompt_branches`, truncates WAL, vacuums the database, and returns the resulting status [@data-script]. +`scripts/manage-data.mjs` is the skill's local data-control entrypoint. It reports `rudderHome`, `databasePath`, and prompt count, and deletes prompt rows only when invoked as `delete --confirm` [@data-script]. Confirmed deletion enables SQLite secure deletion, deletes rows from `prompt_branches`, truncates WAL, vacuums the database, and returns the resulting status [@data-script]. -The skill handles data-control requests separately from test generation. It instructs the agent to use `manage-data.mjs` for status, disable, enable, or delete requests, explain the effect of disabling and deletion, avoid deletion without an explicit request, and stop after completing the data-control task [@skill]. +The skill handles data-control requests separately from test generation. It instructs the agent to use `manage-data.mjs` for status or delete requests, explain that confirmed deletion is irreversible, avoid deletion without an explicit request, and stop after completing the data-control task [@skill]. Tests assert that `disable` is no longer accepted by the data helper [@skill-tests]. ## Validation Contract -`test/skill-runtime.test.ts` exercises the three helper boundaries together: disabled capture blocks prompt writes, the context helper returns branch changes and locally captured prompt text, the backup helper backs up only explicit test paths, and the data helper requires confirmation before deleting prompt rows [@skill-tests]. The OpenAI surface file gives Codex a display name, short description, and default prompt for the same skill package [@openai-surface]. +`test/skill-runtime.test.ts` exercises the helper boundaries together: legacy capture-disable markers do not block prompt writes, the context helper returns branch changes plus captured prompt identifiers and text, the update helper caches registry state and retries nonblocking updates, the backup helper backs up only explicit test paths, and the data helper requires confirmation before deleting prompt rows [@skill-tests]. The OpenAI surface file gives Codex a display name, short description, and default prompt for the same skill package [@openai-surface]. diff --git a/almanac/architecture/runtime/telemetry.md b/almanac/architecture/runtime/telemetry.md index 67fc70f..c4daed5 100644 --- a/almanac/architecture/runtime/telemetry.md +++ b/almanac/architecture/runtime/telemetry.md @@ -1,11 +1,17 @@ --- title: "Telemetry Architecture" -summary: "Rudder telemetry is an opt-in PostHog client with a local anonymous installation identity, environment-controlled opt-out, and explicit shutdown." +summary: "Rudder telemetry is a PostHog client with release-build token injection, local anonymous installation identity, environment-controlled opt-out, and explicit shutdown." topics: [architecture, runtime, telemetry, configuration] sources: - id: telemetry type: file path: src/telemetry.ts + - id: telemetry-build-config + type: file + path: src/telemetry-build-config.ts + - id: publish-workflow + type: file + path: .github/workflows/publish.yml - id: db-client type: file path: src/db/client.ts @@ -14,11 +20,11 @@ sources: path: package.json --- -Rudder telemetry is opt-in runtime infrastructure around `posthog-node`. The module creates a PostHog client only when `POSTHOG_API_KEY` is non-empty and `DO_NOT_TRACK` is not set to `1`; otherwise capture calls are no-ops through optional chaining [@telemetry]. When enabled, events use a stable anonymous installation id stored as `identity.json` under the same Rudder home directory used by [Local State](local-state) [@telemetry] [@db-client]. The package baseline includes `posthog-node` as a runtime dependency, and the telemetry module owns the client lifecycle through capture helpers and an async `shutdown()` function [@package-json] [@telemetry]. +Rudder telemetry is runtime infrastructure around `posthog-node`. The module creates a PostHog client only when a project token is available and `DO_NOT_TRACK` is not set to `1`; otherwise capture calls are no-ops through optional chaining [@telemetry]. Source builds keep the built-in token empty, while the publish workflow rewrites `src/telemetry-build-config.ts` in the release workspace before bundling so published hooks can carry release telemetry defaults without requiring user environment variables [@telemetry-build-config] [@publish-workflow]. When enabled, events use a stable anonymous installation id stored as `identity.json` under the same Rudder home directory used by [Local State](local-state) [@telemetry] [@db-client]. The package lists `posthog-node` in development dependencies and bundles the hook output, so the published plugin still contains telemetry code without declaring a runtime `dependencies` field [@package-json]. The telemetry module owns the client lifecycle through capture helpers and an async `shutdown()` function [@telemetry]. ## Enablement Boundary -Telemetry enablement is decided before a client is constructed. The module reads `POSTHOG_API_KEY` into a constant, reads `POSTHOG_HOST` with the default `https://us.i.posthog.com`, and exposes `telemetryDisabled()` as the `DO_NOT_TRACK === '1'` check [@telemetry]. The internal `client()` function returns `null` when the API key is empty or telemetry is disabled, so `capture()` and `captureException()` can safely call it without requiring callers to branch on configuration [@telemetry]. +Telemetry enablement is decided before a client is constructed. The module chooses the project token from `POSTHOG_PROJECT_TOKEN`, then `POSTHOG_API_KEY`, then `BUILT_IN_POSTHOG_PROJECT_TOKEN`; it chooses the host from `POSTHOG_HOST`, then `BUILT_IN_POSTHOG_HOST`, then `https://us.i.posthog.com` [@telemetry] [@telemetry-build-config]. `telemetryDisabled()` is the `DO_NOT_TRACK === '1'` check [@telemetry]. The internal `client()` function returns `null` when the selected token is empty or telemetry is disabled, so `capture()` and `captureException()` can safely call it without requiring callers to branch on configuration [@telemetry]. When a client is created, it is cached in `_client` and configured with the selected host, `flushAt: 1`, `flushInterval: 0`, and exception autocapture enabled [@telemetry]. The flush settings fit short-lived CLI invocations because each event is sent immediately instead of waiting for a larger batch [@telemetry]. diff --git a/almanac/architecture/tooling/package-baseline.md b/almanac/architecture/tooling/package-baseline.md index 6af4ab1..9675c21 100644 --- a/almanac/architecture/tooling/package-baseline.md +++ b/almanac/architecture/tooling/package-baseline.md @@ -20,11 +20,11 @@ sources: path: .gitignore --- -Rudder's package baseline is the repo's build and distribution frame for the plugin. The package is published as `@ruddercode/rudder-plugin`, uses ESM, requires Node `>=23.6.0`, bundles the prompt hook to `dist/rudder-prompt-hook.mjs`, copies generated Drizzle migrations into `dist/drizzle`, and includes plugin manifests, assets, docs, hooks, skills, `dist`, and `LICENSE` in the npm file allowlist [@package-json]. That baseline connects runtime, plugin, and tooling work to [Contributor Automation](../automation/contributor-automation), because the package scripts define the command set those pages reuse [@package-json]. +Rudder's package baseline is the repo's build and distribution frame for the plugin. The package is published as `@ruddercode/rudder-plugin`, uses ESM, requires Node `>=24.0.0`, bundles the prompt hook to `dist/rudder-prompt-hook.mjs`, copies generated Drizzle migrations into `dist/drizzle`, and includes plugin manifests, assets, docs, hooks, skills, `dist`, and `LICENSE` in the npm file allowlist [@package-json]. That baseline connects runtime, plugin, and tooling work to [Contributor Automation](../automation/contributor-automation), because the package scripts define the command set those pages reuse [@package-json]. ## Package Contract -`package.json` is the public package contract. It names the package, version `0.1.0`, Apache-2.0 license, GitHub repository metadata, supported Node engine, package scripts, and package file allowlist [@package-json]. The manifest intentionally carries plugin artifacts rather than a `main`, `types`, or package-root `exports` entry; plugin hosts load the installed hook through `hooks/hooks.json`, and tests enforce that the manifest does not define runtime dependencies or npm workspaces [@package-json] [@plugin-tests]. +`package.json` is the public package contract. It names the package, version `0.1.3`, Apache-2.0 license, GitHub repository metadata, supported Node engine, package scripts, and package file allowlist [@package-json]. The manifest intentionally carries plugin artifacts rather than a `main`, `types`, or package-root `exports` entry; plugin hosts load the installed hook through `hooks/hooks.json`, and tests enforce that the manifest does not define runtime dependencies or npm workspaces [@package-json] [@plugin-tests]. The package file allowlist keeps distribution narrow but plugin-complete. `.claude-plugin`, `.codex-plugin`, `assets`, `docs`, `hooks`, `skills`, `dist`, and `LICENSE` ship with the package [@package-json]. Build output and transient development files are excluded from the working tree by `.gitignore`, which ignores `node_modules/`, `dist/`, TypeScript build info, logs, `.env` files except `.env.example`, coverage, and common editor files [@gitignore]. diff --git a/almanac/architecture/tooling/plugin-package.md b/almanac/architecture/tooling/plugin-package.md index 42f1eb8..27b1963 100644 --- a/almanac/architecture/tooling/plugin-package.md +++ b/almanac/architecture/tooling/plugin-package.md @@ -37,17 +37,17 @@ sources: # Rudder Plugin Package -The repository root is now the publishable Rudder plugin package. `package.json` names the package `@ruddercode/rudder-plugin`, requires Node `>=23.6.0`, and includes plugin-specific artifacts such as `.claude-plugin`, `.codex-plugin`, `assets`, `docs`, `hooks`, `skills`, and `dist` in the npm file allowlist [@package-json]. The package carries both Claude Code and Codex plugin manifests, a public marketplace catalog that points at the npm package, the Rudder skill, and a bundled prompt-capture hook [@claude-manifest] [@codex-manifest] [@marketplace] [@hooks] [@skill]. +The repository root is the publishable Rudder plugin package. `package.json` names the package `@ruddercode/rudder-plugin`, requires Node `>=24.0.0`, and includes plugin-specific artifacts such as `.claude-plugin`, `.codex-plugin`, `assets`, `docs`, `hooks`, `skills`, and `dist` in the npm file allowlist [@package-json]. The package carries both Claude Code and Codex plugin manifests, a public marketplace catalog that points at the npm package, the Rudder skill, and a bundled prompt-capture hook [@claude-manifest] [@codex-manifest] [@marketplace] [@hooks] [@skill]. ## Distribution Shape The Claude manifest and Codex manifest share the public plugin name `rudder`, version, description, license, repository, keywords, and `./skills/` path [@claude-manifest] [@codex-manifest]. The Claude manifest also points at `./hooks/hooks.json`, while the Codex manifest carries interface metadata such as display name, short description, category, default prompt, icon, logo, privacy URL, and terms URL [@claude-manifest] [@codex-manifest]. -The marketplace catalog under `.claude-plugin/marketplace.json` lists one plugin named `rudder` and resolves it from npm package `@ruddercode/rudder-plugin` version `0.1.0` on the public npm registry [@marketplace]. The install docs describe Claude Code and Codex marketplace installation separately but state that both use the same npm-backed plugin package [@install-doc]. +The marketplace catalog under `.claude-plugin/marketplace.json` lists one plugin named `rudder` and resolves it from npm package `@ruddercode/rudder-plugin` version `0.1.3` on the public npm registry [@marketplace]. Tests enforce that the package version is synchronized across `package.json`, `package-lock.json`, both plugin manifests, and both marketplace version fields [@plugin-tests]. The install docs describe Claude Code and Codex marketplace installation separately but state that both use the same npm-backed plugin package [@install-doc]. ## Bundled Hook -`hooks/hooks.json` registers command hooks for `UserPromptSubmit` and `Stop` [@hooks]. Each command executes Node with `--input-type=module`, resolves the plugin root from `PLUGIN_ROOT` or `CLAUDE_PLUGIN_ROOT`, and imports `dist/rudder-prompt-hook.mjs` from that root [@hooks]. The source executable reads JSON hook payloads from stdin, infers Codex from `PLUGIN_ROOT`, infers Claude Code from `CLAUDE_PLUGIN_ROOT`, sets `RUDDER_MIGRATIONS_PATH` to the installed `dist/drizzle` folder, records the prompt hook event, catches failures, and closes the database handle [@hook-bin]. +`hooks/hooks.json` registers command hooks for `UserPromptSubmit` and `Stop` [@hooks]. Each command executes Node with `--input-type=module`, resolves the plugin root from `PLUGIN_ROOT` or `CLAUDE_PLUGIN_ROOT`, and imports `dist/rudder-prompt-hook.mjs` from that root [@hooks]. The source executable reads JSON hook payloads from stdin, infers Codex from `PLUGIN_ROOT`, infers Claude Code from `CLAUDE_PLUGIN_ROOT`, sets `RUDDER_MIGRATIONS_PATH` to the installed `dist/drizzle` folder, records the prompt hook event, catches failures, reports hook exceptions through telemetry best-effort, closes the database handle, and shuts down telemetry without printing model-visible output [@hook-bin]. The `build` script creates the installed hook artifact by bundling `bin/rudder-prompt-hook.ts` with esbuild for Node ESM output at `dist/rudder-prompt-hook.mjs`, then copying committed Drizzle migrations into `dist/drizzle` [@package-json]. `pretest` and `prepack` both run the build, so tests and packed artifacts use a freshly generated bundle [@package-json]. Plugin package tests enforce matching Claude/Codex metadata, required package file entries, marketplace npm source fields, hook command shape, and silent prompt-hook execution for both `PLUGIN_ROOT` and `CLAUDE_PLUGIN_ROOT` environments [@plugin-tests]. diff --git a/almanac/concepts/product/intent-driven-test-generation.md b/almanac/concepts/product/intent-driven-test-generation.md index 0b8b407..e518063 100644 --- a/almanac/concepts/product/intent-driven-test-generation.md +++ b/almanac/concepts/product/intent-driven-test-generation.md @@ -1,6 +1,6 @@ --- title: "Intent-Driven Test Generation" -summary: "Intent-driven test generation is Rudder's workflow for turning locally captured coding-session intent and worktree changes into verified unit tests." +summary: "Intent-driven test generation is Rudder's workflow for turning captured coding-session intent into tagged tests and prompt-backed code changes." topics: [concepts, product-intent, test-generation-intent] sources: - id: readme @@ -19,22 +19,22 @@ sources: # Intent-Driven Test Generation -Intent-driven test generation is the Rudder product model in which a coding agent uses the user's session prompts, answers, and worktree changes to generate unit tests for newly introduced production code. The product premise is that a session contains more behavioral intent than a diff: prompts can name expected behavior, edge cases, and tradeoffs that never become comments or commit messages [@readme]. The current plugin implements the local context layer by capturing submitted prompts, reconciling them to branches, and giving the Rudder skill a JSON view of branch prompts plus changed paths [@prompt-hook] [@context-script]. +Intent-driven test generation is the Rudder product model in which a coding agent uses captured session prompts and worktree changes to write tests that are traceable to user intent. The README describes Rudder as a local Claude Code and Codex plugin that generates tests from prompts and uses coverage as a proxy for how much generated code reflects the developer's own decisions [@readme]. The current plugin implements the local context layer by capturing submitted prompts, reconciling them to branches, and giving the Rudder skill a JSON view of branch prompts plus changed paths [@prompt-hook] [@context-script]. ## Intent Source -The central input is the current coding-agent session. Rudder is designed to run inside the same session where the feature was built, so the workflow can use the user's prompts and later answers as product intent instead of requiring a separate specification document [@readme]. [Prompt History](../runtime/prompt-history) covers the implemented local prompt store that supplies this context to the skill [@prompt-hook] [@context-script]. +The central input is the current coding-agent session. Rudder runs as a plugin for the user's existing coding agent and stores prompt data locally, so the workflow can use captured prompts and later answers as product intent instead of requiring a separate specification document [@readme]. [Prompt History](../runtime/prompt-history) covers the implemented local prompt store that supplies this context to the skill [@prompt-hook] [@context-script]. -Worktree changes provide the other input. The proposed flow resolves a merge base, identifies production code introduced in the worktree, and uses the user's prompts to understand the behavior that code is meant to implement [@readme]. This makes the diff the implementation target and the prompt history the behavioral target. +Worktree changes provide the other input. `scripts/context.mjs` resolves a merge base, classifies changed test paths and other paths, and returns prompt records for the active repository branch [@context-script]. This makes the diff the implementation target and the prompt history the behavioral target. ## Workflow Shape -Rudder starts from a fresh test slate before generation. The README states that Rudder reverts testing code already added or changed in the worktree so the generated suite is derived from user intent rather than from an earlier test-writing attempt [@readme]. The installed skill turns that into an explicit confirmation workflow around exact test paths and a recoverable backup before any reset [@skill]. The linked [Test Intent Standards](test-intent-standards) page explains the direct-intent rule that decides when changes to existing tests are treated as intentional requirements. +Rudder starts from a controlled test reset before generation. The installed skill requires the agent to show exact tracked and untracked test paths, get explicit confirmation, create a recoverable backup, and then restore only the confirmed test paths to the merge-base state [@skill]. When a confirmed path already contains Rudder source-intent tags, the agent records those tagged test cases before the reset and attempts to restore only those cases plus the smallest required supporting code afterward [@skill]. The linked [Test Intent Standards](test-intent-standards) page explains the direct-intent and source-tag rules that decide which expectations can be generated or restored. -After the reset, the current agent owns the unit-test changes for the workflow while production code remains unchanged [@readme]. The agent generates tests, the repository's native test and coverage tools run, and uncovered production code becomes the basis for narrow questions when coverage is still below the target [@readme]. A useful question changes a concrete test expectation rather than asking for information the repository or session already provides [@readme]. +After the reset, every generated or rewritten test case must carry an immediately preceding source-intent comment in `//` form, using identifiers from captured prompt records rather than prompt text [@skill]. Coverage is loop control rather than a source of new expectations: when coverage is below target after a green first pass, the agent asks one concrete question about an uncovered behavior and waits for a captured answer before writing the next test [@skill]. ## Generation Ownership -The local version is bring-your-own-key. Rudder does not choose a model or make a separate model API call; the user's current coding agent generates tests with the model and credentials already configured for that agent [@readme]. The product is therefore a skill-guided workflow backed by deterministic local context and worktree tools, not a provider-specific test generator [@readme] [@skill]. [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow) records that product decision. +The local version is bring-your-own-agent. Rudder does not choose a model or make a separate model API call; the user's current coding agent generates tests with the model and credentials already configured for that agent [@readme] [@skill]. The product is therefore a skill-guided workflow backed by deterministic local context and worktree tools, not a provider-specific test generator [@readme] [@skill]. [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow) records that product decision. -This ownership model keeps the feedback loop inside the coding session that produced the implementation. Prompts, generated tests, coverage results, follow-up questions, and user answers all stay in that session, and each answer feeds the next test-generation pass until the coverage target is reached [@readme]. +This ownership model keeps the feedback loop inside the coding session that produced the implementation. Production changes are now allowed only inside a prompt-backed red-green cycle: write the tagged test first, observe the expected failure, make the smallest implementation change, rerun the narrow test, and measure coverage only after the suite is green [@skill]. diff --git a/almanac/concepts/product/test-intent-standards.md b/almanac/concepts/product/test-intent-standards.md index 884aeaf..1225dd4 100644 --- a/almanac/concepts/product/test-intent-standards.md +++ b/almanac/concepts/product/test-intent-standards.md @@ -1,11 +1,8 @@ --- title: "Test Intent Standards" -summary: "Test intent standards define how Rudder distinguishes direct user intent from inferred or preexisting test changes during generation." +summary: "Test intent standards define how Rudder ties generated tests, restored test cases, and coverage questions to captured user intent." topics: [concepts, product-intent, test-generation-intent] sources: - - id: readme - type: file - path: README.md - id: skill type: file path: skills/rudder/SKILL.md @@ -16,22 +13,28 @@ sources: # Test Intent Standards -Test intent standards are the rules that keep Rudder's generated unit tests grounded in what the user directly intended during a coding session. They require a fresh test slate, treat changes to existing tests as intentional only when the user's prompts directly encode that intent, and use narrow questions to resolve ambiguities that affect test expectations [@readme]. The installed Rudder skill operationalizes the same rules by requiring exact-path confirmation, backup creation, and production-code immutability during generation [@skill]. These standards sit inside [Intent-Driven Test Generation](intent-driven-test-generation) and constrain the [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow). +Test intent standards are the rules that keep Rudder's generated unit tests grounded in what the user directly intended during a coding session. They require generated or rewritten test cases to be traceable to captured prompt records, reset confirmed test paths through a recoverable backup, preserve only Rudder-tagged generated tests after that reset when they can be isolated, and use narrow questions to resolve uncovered behavior [@skill]. These standards sit inside [Intent-Driven Test Generation](intent-driven-test-generation) and constrain the [BYOK Skill Workflow](../../decisions/product/byok-skill-workflow). ## Direct Intent -The direct-intent standard applies when the worktree already contains changes to existing tests. The README defines those changes as important signals because they can show that established behavior is changing, but it also says Rudder should preserve such a change as a requirement only when the current session's prompts directly express the intent to change it [@readme]. If the prompts do not encode that intent, Rudder should flag the test change to the user in the current session before continuing [@readme]. +The direct-intent standard applies to every generated or expanded expectation. The skill says to generate or expand a test only when a captured user prompt or answer explicitly requires the expectation, and it forbids adding tests merely to execute uncovered code, match the implementation, improve coverage, or exercise a defensive case [@skill]. -This rule prevents regenerated tests from silently accepting behavior just because a test file already changed. The source of truth for a changed expectation is the user's expressed intent, not the mere presence of a changed assertion or fixture. +This rule prevents regenerated tests from silently accepting behavior just because a test file already changed or a coverage report has an uncovered branch. The source of truth for a changed expectation is the user's captured intent, not the mere presence of a changed assertion, fixture, or implementation branch [@skill]. ## Fresh Test Slate -The fresh test slate is the reset that happens before generation begins. Rudder is expected to revert all testing code introduced or changed in the worktree, including committed, staged, unstaged, and untracked test changes relative to the merge base [@readme]. The current agent identifies test paths from repository structure and conventions instead of relying on one language or test framework [@readme]. +The fresh test slate is the reset that happens before generation begins. The skill requires the agent to show the exact tracked and untracked test paths, get explicit confirmation, back up only those paths, verify the backup, and restore only the confirmed paths to the merge-base state [@skill]. `backup-tests.mjs` supports that scope by requiring each affected path explicitly, rejecting paths outside the repository, writing a binary-capable tracked patch, and copying listed untracked test files into the backup [@backup-script]. + +The reset has a narrow restoration exception for previously generated Rudder tests. Before clearing confirmed paths, the agent inspects them for test cases with an immediately preceding source-intent tag, records those cases and tags, and after the reset attempts to restore only those cases plus the smallest required supporting code [@skill]. A tag on a helper, fixture, or non-adjacent comment is not enough, and untagged tests must not be restored wholesale [@skill]. + +## Source-Intent Tags + +Every generated or rewritten test case gets one language-appropriate comment immediately above the test case in `//` form [@skill]. The identifiers come from captured prompt records returned by `scripts/context.mjs`, and the skill forbids copying prompt text into test code [@skill]. -The reset has a narrow scope. Production code remains unchanged, and the current agent owns the worktree's unit-test changes only for the duration of the workflow [@readme]. `backup-tests.mjs` supports that scope by requiring each affected path explicitly, rejecting paths outside the repository, writing a binary-capable tracked patch, and copying listed untracked test files into the backup [@backup-script]. That makes the generated tests a product of session intent and repository behavior rather than a continuation of earlier test edits. +The tag is a traceability contract, not a decoration. It identifies which captured prompt authorized the expectation, lets a later Rudder reset preserve only generated tests that still have adjacent source tags, and keeps unchanged preexisting tests, shared helpers, and fixtures outside the generated-test set [@skill]. ## Questions And Coverage -Rudder should ask questions only when they resolve an ambiguity that changes a test expectation. The README says Rudder should not ask for information it can infer from the repository, implementation, existing test conventions, or coding session, and gives the shape of a useful question as one that decides a concrete behavior under a specific condition [@readme]. +Rudder should ask questions only when they resolve an ambiguity that changes a test expectation. After the first green test pass, if coverage is below target, the skill requires the agent to stop editing tests, select one uncovered behavior, ask one concrete question, and wait for the user's answer before writing the next test [@skill]. -Coverage is the loop control, not the source of intent. The proposed workflow runs the repository's native unit-test and coverage tooling, measures coverage of production code introduced in the worktree, asks concrete questions when coverage is below the configured minimum, incorporates each answer into the next pass, and continues until the target is reached before PR publication [@readme]. Contributors use [Run Checks](../../guides/contributor/run-checks) for the repository's validation procedure outside this product-generation loop. +Coverage is the loop control, not the source of intent. The skill requires a captured prompt record for each follow-up answer before adding the expectation that answer authorizes, and it stops below target when the answer is missing, declined, or not captured [@skill]. Contributors use [Run Checks](../../guides/contributor/run-checks) for the repository's validation procedure outside this product-generation loop. diff --git a/almanac/concepts/runtime/prompt-history.md b/almanac/concepts/runtime/prompt-history.md index d8d98d2..50acbe8 100644 --- a/almanac/concepts/runtime/prompt-history.md +++ b/almanac/concepts/runtime/prompt-history.md @@ -1,6 +1,6 @@ --- title: "Prompt History" -summary: "Prompt history is Rudder's local prompt text context for intent-driven test generation, stored per agent prompt and reconciled to the active Git branch." +summary: "Prompt history is Rudder's local prompt context for intent-driven test generation, stored per agent prompt and reconciled to the active Git branch." topics: [concepts, product-intent, prompt-history, prompt-capture] sources: - id: schema @@ -12,9 +12,9 @@ sources: - id: prompt-hook type: file path: src/prompt-hook.ts - - id: prompt-control + - id: transcript type: file - path: src/prompt-control.ts + path: src/transcript.ts - id: context-script type: file path: skills/rudder/scripts/context.mjs @@ -25,7 +25,7 @@ sources: # Prompt History -Prompt history is Rudder's local record of prompt text that can explain user intent for generated tests. The README says coding-session prompts and follow-up answers can name expected behavior, edge cases, and tradeoffs that never appear in code diffs [@readme]. The implemented runtime now stores submitted prompt text in `prompt_branches`, associates each prompt with source/session/prompt IDs, repository, branch, and timestamps, and exposes lookup helpers for session and branch context [@schema] [@prompt-tagger]. +Prompt history is Rudder's local record of prompt context that can explain user intent for generated tests. The README says coding-session prompts and follow-up answers can name expected behavior, edge cases, and tradeoffs that never appear in code diffs [@readme]. The implemented runtime stores submitted prompt text in `prompt_branches`, associates each prompt with source/session/prompt IDs, repository, branch, timestamps, and optional previous agent output, and exposes lookup helpers for session and branch context [@schema] [@prompt-tagger]. ## Product Meaning @@ -35,10 +35,10 @@ The current implementation gives the [Rudder Skill Runtime](../../architecture/r ## Capture Model -Prompt capture starts from coding-agent hooks. `recordPromptHookEvent()` normalizes Claude Code, Codex, and Cursor payloads, records prompt text on submit events, and reconciles the prompt to the active branch on stop events [@prompt-hook]. `recordPromptBranch()` writes the submitted prompt with the branch active before the turn runs, while `reconcilePromptBranch()` updates the row to the branch active after the turn and sets `reconciled_at` [@prompt-tagger]. +Prompt capture starts from coding-agent hooks. `recordPromptHookEvent()` normalizes Claude Code, Codex, and Cursor payloads, records prompt text on submit events, and reconciles the prompt to the active branch on stop events [@prompt-hook]. When a submit payload includes `transcript_path`, the hook reads the latest visible assistant text from that JSONL transcript and stores it as `previous_agent_output` when one is found [@prompt-hook] [@transcript]. -Prompt capture can be disabled before a write. `promptCaptureDisabled()` returns true when `RUDDER_DISABLE_PROMPT_CAPTURE` is exactly `1` or when the `prompt-capture-disabled` marker exists under the Rudder home directory [@prompt-control]. +`recordPromptBranch()` writes the submitted prompt with the branch active before the turn runs, while `reconcilePromptBranch()` updates the row to the branch active after the turn and sets `reconciled_at` [@prompt-tagger]. Replaying the same source/session/prompt ID updates prompt text, keeps the earliest submission time, and preserves the first non-null previous agent output by coalescing the stored value with the replayed one [@prompt-tagger]. ## Working Implication -When updating the product workflow, treat prompt history as local and branch-scoped. `skills/rudder/scripts/context.mjs` reads prompts for the resolved repository and branch from `prompt_branches` and returns them beside the branch diff, so the skill can combine implementation changes with user-stated intent [@context-script]. Use [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt Branches Schema](../../reference/database/prompt-branches-schema), and [Use Prompt Capture](../../guides/runtime/use-prompt-capture) for current implementation work. +When updating the product workflow, treat prompt history as local and branch-scoped. `skills/rudder/scripts/context.mjs` reads prompt identifiers, text, and timestamps for the resolved repository and branch from `prompt_branches` and returns them beside the branch diff, so the skill can combine implementation changes with user-stated intent [@context-script]. Use [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt Branches Schema](../../reference/database/prompt-branches-schema), and [Use Prompt Capture](../../guides/runtime/use-prompt-capture) for current implementation work. diff --git a/almanac/decisions/database/generated-drizzle-migrations.md b/almanac/decisions/database/generated-drizzle-migrations.md index 74d5317..244669e 100644 --- a/almanac/decisions/database/generated-drizzle-migrations.md +++ b/almanac/decisions/database/generated-drizzle-migrations.md @@ -15,6 +15,9 @@ sources: - id: prompt-migration type: file path: drizzle/20260722200723_prompt-branch-links/migration.sql + - id: previous-output-migration + type: file + path: drizzle/20260723191552_capture-previous-agent-output/migration.sql - id: drizzle-config type: file path: drizzle.config.ts @@ -28,17 +31,17 @@ sources: # Generated Drizzle Migrations -Rudder's database schema decision is that generated Drizzle migrations are part of runtime startup. `openDb()` creates the local SQLite database, wraps it with Drizzle, and calls the Drizzle migrator against the configured migrations folder before exposing the cached database handles [@db-client]. The current migration sequence creates `prompt_branches` after the initial session-branch migration and drops the older `session_branches` table, while the plugin build copies `drizzle/` into `dist/drizzle` so the installed prompt hook can run the same migrations [@initial-migration] [@prompt-migration] [@package-json]. +Rudder's database schema decision is that generated Drizzle migrations are part of runtime startup. `openDb()` creates the local SQLite database, wraps it with Drizzle, and calls the Drizzle migrator against the configured migrations folder before exposing the cached database handles [@db-client]. The current migration sequence creates `prompt_branches` after the initial session-branch migration, drops the older `session_branches` table, and then adds nullable `previous_agent_output`, while the plugin build copies `drizzle/` into `dist/drizzle` so the installed prompt hook can run the same migrations [@initial-migration] [@prompt-migration] [@previous-output-migration] [@package-json]. ## Status -Accepted for the current prompt-capture database. The active schema surface is split by role: `src/db/schema.ts` declares `prompt_branches`, `drizzle.config.ts` tells Drizzle Kit to generate SQLite migrations into `./drizzle`, the generated SQL creates the live prompt table, and `openDb()` applies those migrations during runtime database initialization [@schema] [@drizzle-config] [@prompt-migration] [@db-client]. +Accepted for the current prompt-capture database. The active schema surface is split by role: `src/db/schema.ts` declares `prompt_branches`, `drizzle.config.ts` tells Drizzle Kit to generate SQLite migrations into `./drizzle`, the generated SQL creates and extends the live prompt table, and `openDb()` applies those migrations during runtime database initialization [@schema] [@drizzle-config] [@prompt-migration] [@previous-output-migration] [@db-client]. ## Context The runtime database must be usable as soon as a local process asks for it, but schema creation also needs to survive plugin packaging. `openDb()` reads `RUDDER_MIGRATIONS_PATH` when it is set and otherwise falls back to the repository `drizzle/` directory relative to `src/db/client.ts` [@db-client]. `package.json` therefore makes `build` bundle `bin/rudder-prompt-hook.ts` into `dist/rudder-prompt-hook.mjs` and copy `drizzle/` into `dist/drizzle` after clearing `dist` [@package-json]. -The prompt migration creates `prompt_branches`, adds repository/branch and session indexes, and drops `session_branches` [@prompt-migration]. `test/migrations.test.ts` verifies runtime behavior instead of only checking the schema declaration: it opens a new database through `openDb()`, confirms `prompt_branches` is present, confirms `session_branches` is absent, and confirms Drizzle recorded two migration rows [@migration-tests]. +The prompt migration creates `prompt_branches`, adds repository/branch and session indexes, and drops `session_branches` [@prompt-migration]. The next migration adds nullable `previous_agent_output` to that table [@previous-output-migration]. `test/migrations.test.ts` verifies runtime behavior instead of only checking the schema declaration: it opens a new database through `openDb()`, confirms `prompt_branches` is present, confirms `session_branches` is absent, confirms `previous_agent_output` is nullable, and confirms Drizzle recorded three migration rows [@migration-tests]. ## Decision diff --git a/almanac/decisions/product/byok-skill-workflow.md b/almanac/decisions/product/byok-skill-workflow.md index 934e91c..656c9b6 100644 --- a/almanac/decisions/product/byok-skill-workflow.md +++ b/almanac/decisions/product/byok-skill-workflow.md @@ -1,6 +1,6 @@ --- title: "BYOK Skill Workflow" -summary: "Rudder's product direction is to guide the user's current coding agent with a local skill workflow instead of making separate model calls itself." +summary: "Rudder guides the user's current coding agent with a local skill workflow instead of making separate model calls itself." topics: [decisions, product-intent] sources: - id: product-readme @@ -20,24 +20,24 @@ sources: path: skills/rudder/scripts/backup-tests.mjs --- -Rudder's BYOK skill workflow decision is that test generation happens inside the user's existing coding-agent session, using that agent's configured model access and credentials, rather than through a separate Rudder-owned model call [@product-readme]. The root plugin package ships the Rudder skill and deterministic helper scripts; the skill gathers local prompt intent, inspects the worktree, confirms and backs up test resets, directs the agent to generate unit tests, runs repository tooling, measures coverage, and asks follow-up questions in the same session [@plugin-package] [@skill]. This decision ties [intent-driven test generation](../../concepts/product/intent-driven-test-generation), [test intent standards](../../concepts/product/test-intent-standards), and [prompt history](../../concepts/runtime/prompt-history) into one local workflow. +Rudder's BYOK skill workflow decision is that test generation and prompt-backed production edits happen inside the user's existing coding-agent session, using that agent's configured model access and credentials, rather than through a separate Rudder-owned model call [@product-readme] [@skill]. The root plugin package ships the Rudder skill and deterministic helper scripts; the skill gathers local prompt intent, inspects the worktree, checks for plugin updates, confirms and backs up test resets, directs the agent through tagged tests and red-green implementation changes, runs repository tooling, measures coverage, and asks follow-up questions in the same session [@plugin-package] [@skill]. This decision ties [intent-driven test generation](../../concepts/product/intent-driven-test-generation), [test intent standards](../../concepts/product/test-intent-standards), and [prompt history](../../concepts/runtime/prompt-history) into one local workflow. ## Status -Accepted and partially implemented. The README lists "BYOK generation" as a product decision and says the user's current coding agent performs generation with the user's existing model credentials [@product-readme]. The current package implements the delivery mechanism as a local plugin skill with helper scripts for context gathering and exact-path test backups, while the host agent still owns reasoning and test generation [@plugin-package] [@skill] [@context-script] [@backup-script]. +Accepted and implemented as the current plugin workflow. The README describes Rudder as a local plugin for Claude Code and Codex that uses the agent and model the user already has configured [@product-readme]. The current package implements the delivery mechanism as a local plugin skill with helper scripts for context gathering and exact-path test backups, while the host agent owns reasoning, test edits, and any smallest production change required by a prompt-backed red-green cycle [@plugin-package] [@skill] [@context-script] [@backup-script]. ## Context -Rudder's proposed workflow depends on intent that exists in the current coding session. The README says prompts can explain wanted behavior, edge cases, and tradeoffs that do not appear in comments or commit messages, and Rudder uses that local session context to create tests for production code in the current worktree [@product-readme]. The same document says follow-up questions should stay concrete and should ask only for information the repository, implementation, existing test conventions, or current session cannot infer [@product-readme]. +Rudder's workflow depends on intent that exists in the current coding session. The README says Rudder generates tests from prompts, stores prompt data locally, and runs directly in the user's coding-agent session [@product-readme]. The skill turns that product model into a direct-intent contract: every generated expectation must trace to a captured prompt record, and missing coverage must become one concrete question before the next test is written [@skill]. A separate model call would move generation away from the session that produced the implementation. The README instead places prompt reading, generated tests, coverage results, questions, and answers inside the current coding-agent session [@product-readme]. ## Decision -Rudder is delivered to the user's coding agent as a skill plus deterministic local helper tools. The skill defines the workflow rules for gathering session intent, evaluating test changes, clearing the test slate, generating tests, running native tooling, measuring coverage, and asking the next question [@skill]. Local tools handle deterministic worktree, backup, and prompt-data operations, while the user's current agent handles reasoning and generation [@skill] [@context-script] [@backup-script]. +Rudder is delivered to the user's coding agent as a skill plus deterministic local helper tools. The skill defines the workflow rules for update notices, session intent, test-path review, tagged generated tests, red-green implementation cycles, native tooling, coverage measurement, and follow-up questions [@skill]. Local tools handle deterministic worktree, backup, prompt-data, and plugin-update operations, while the user's current agent handles reasoning and generation [@skill] [@context-script] [@backup-script]. ## Consequences -The decision keeps generation repository- and provider-agnostic. The README says the workflow should discover and use the repository's own language, test framework, commands, and coverage tooling, and should not tie generation to one provider [@product-readme]. It also keeps every follow-up question in the session where the feature was implemented, so user answers become part of the same intent stream used for later generation passes [@product-readme]. The implemented helper layer can supply branch changes, captured prompts, and recoverable test backups, but the host agent still owns behavioral judgment and generated test edits [@context-script] [@backup-script] [@skill]. +The decision keeps generation repository- and provider-agnostic. The README says Rudder uses the repository's own test and coverage tools and keeps test generation with the coding agent and model the user already uses [@product-readme]. It also keeps every follow-up question in the session where the feature was implemented, so user answers become captured prompt records for later generation passes [@skill]. The implemented helper layer can supply branch changes, captured prompts, update checks, and recoverable test backups, but the host agent still owns behavioral judgment and generated edits [@context-script] [@backup-script] [@skill]. -The tradeoff is that Rudder's local workflow must express instructions clearly enough for supported coding agents to execute. The helper scripts can provide repository context, prompt records, and recoverable backups, but they do not determine behavioral intent or generate tests [@context-script] [@backup-script] [@skill]. Future product work should preserve this boundary unless a later decision explicitly moves model selection or generation into Rudder itself. +The tradeoff is that Rudder's local workflow must express instructions clearly enough for supported coding agents to execute. The helper scripts can provide repository context, prompt records, update commands, and recoverable backups, but they do not determine behavioral intent or generate tests [@context-script] [@backup-script] [@skill]. Future product work should preserve this boundary unless a later decision explicitly moves model selection or generation into Rudder itself. diff --git a/almanac/decisions/release/artifact-checked-plugin-publishing.md b/almanac/decisions/release/artifact-checked-plugin-publishing.md index f792275..5e68995 100644 --- a/almanac/decisions/release/artifact-checked-plugin-publishing.md +++ b/almanac/decisions/release/artifact-checked-plugin-publishing.md @@ -24,7 +24,7 @@ Accepted in the current plugin release workflows. `publish.yml` runs on pushes t ## Context -The package version is the release coordinate, but the npm registry is the npm publish source of truth. The publish workflow checks `npm view "@ruddercode/rudder-plugin@" version --registry=https://registry.npmjs.org`; success disables npm publishing, while npm 404 enables publishing [@publish-workflow]. It separately checks whether the package exists at all, and a missing package plus missing version marks the publication as a bootstrap publish [@publish-workflow]. +The package version is the release coordinate, but the npm registry is the npm publish source of truth. The publish workflow checks `npm view "@ruddercode/rudder-plugin@" version --registry=https://registry.npmjs.org`; success disables npm publishing, while npm 404 enables publishing [@publish-workflow]. The plugin tag and GitHub Release are separate artifacts. Both workflows derive `tag="rudder-plugin-v${version}"`, check whether that tag exists, and check whether `gh api repos/${GITHUB_REPOSITORY}/releases/tags/${tag}` returns a release or 404 [@publish-workflow] [@release-alert]. This means a missing tag can be created even when npm already has the package version, and a missing GitHub Release can be backfilled for an existing tag [@publish-workflow]. @@ -34,6 +34,6 @@ Rudder will publish the root plugin package to npmjs.org, create plugin-specific ## Consequences -The first npm publication needs `NPM_TOKEN` because the package must exist before Trusted Publisher setup can be configured; the publish workflow fails bootstrap publication when that secret is absent [@publish-workflow]. Later publications still run through the same validation step, which checks agent layout, typecheck, tests, build, and `npm pack --dry-run` before publishing [@publish-workflow]. +Publishing uses npm Trusted Publishing through the workflow's `id-token: write` permission, so the publish step does not set `NPM_TOKEN` or `NODE_AUTH_TOKEN` [@publish-workflow]. Release runs still validate agent layout, typecheck, tests, build, and `npm pack --dry-run` before publishing, and those validation and publish steps run with `DO_NOT_TRACK=1` so release checks do not emit telemetry [@publish-workflow]. -Pull requests get an early warning. The release-alert job writes or updates a sticky comment marked with ``, reports whether merging will publish to npmjs.org, use the bootstrap token, create the plugin tag, or create the GitHub Release, and switches to a no-release note when all plugin artifacts already exist for the manifest version [@release-alert]. Release preparation should use [Prepare Package Release](../../guides/release/prepare-package-release) and [GitHub Workflows](../../reference/automation/github-workflows) instead of relying on a manual tag-first process. +Pull requests get an early warning. The release-alert job writes or updates a sticky comment marked with ``, reports whether merging will publish to npmjs.org, create the plugin tag, or create the GitHub Release, and switches to a no-release note when all plugin artifacts already exist for the manifest version [@release-alert]. Release preparation should use [Prepare Package Release](../../guides/release/prepare-package-release) and [GitHub Workflows](../../reference/automation/github-workflows) instead of relying on a manual tag-first process. diff --git a/almanac/getting-started.md b/almanac/getting-started.md index e7876da..34b89c6 100644 --- a/almanac/getting-started.md +++ b/almanac/getting-started.md @@ -43,19 +43,19 @@ Getting started is the entry point for reading Rudder's wiki as a future coding Use implementation-backed pages first when a task touches existing code. [Rudder Plugin Package](architecture/tooling/plugin-package), [Prompt Branch Store](architecture/runtime/prompt-branch-store), [Rudder Skill Runtime](architecture/runtime/rudder-skill-runtime), [Local State](architecture/runtime/local-state), [Telemetry](architecture/runtime/telemetry), [Package Baseline](architecture/tooling/package-baseline), and [Contributor Automation](architecture/automation/contributor-automation) explain the current package, runtime, and automation surfaces. -Protected files are a separate agent-safety boundary. Start with [Protected Paths](reference/contributor/protected-paths) when a task touches root documentation, assets, or agent compatibility paths, because Danger protects `README.md`, `LICENSE`, `CLAUDE.md`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` for detected agent-authored pull requests [@dangerfile]. +Protected files are a separate agent-safety boundary. Start with [Protected Paths](reference/contributor/protected-paths) when a task touches root documentation, public docs, assets, or agent compatibility paths, because Danger protects `README.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `CLAUDE.md`, `docs/**`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` for detected agent-authored pull requests [@dangerfile]. ## Runtime State And Prompts The current runtime code is small but real. `rudderHome()` resolves `RUDDER_HOME` or falls back to `~/.rudder`, `dbPath()` stores `rudder.db` under that root, and `openDb()` creates the directory, restricts local state permissions when possible, enables SQLite WAL mode, sets a 5000 ms busy timeout, enables secure deletion, applies generated Drizzle migrations, and initializes Drizzle over the same SQLite client [@db-client]. Start with [Local State](architecture/runtime/local-state) for the state-root model, then read [Prompt Branch Store](architecture/runtime/prompt-branch-store) and [Prompt Branches Schema](reference/database/prompt-branches-schema) when working with implemented prompt/worktree persistence. -Use [Use Prompt Capture](guides/runtime/use-prompt-capture) when hook or skill code needs to record, query, disable, or delete prompt data. The hook runtime normalizes Claude Code, Codex, and Cursor submit/stop payloads, while the skill context helper reads prompt records for the active repository branch [@prompt-hook] [@skill]. +Use [Use Prompt Capture](guides/runtime/use-prompt-capture) when hook or skill code needs to record, query, or delete prompt data. The hook runtime normalizes Claude Code, Codex, and Cursor submit/stop payloads, while the skill context helper reads prompt records for the active repository branch [@prompt-hook] [@skill]. -Telemetry uses the same local-state root for its anonymous identity file. It creates a PostHog client only when `POSTHOG_API_KEY` is set and `DO_NOT_TRACK` is not `1`, and its capture helpers become no-ops when the client is unavailable [@telemetry]. Read [Telemetry](architecture/runtime/telemetry) with [Environment Variables](reference/configuration/environment-variables) before changing event capture, opt-out behavior, identity storage, or shutdown behavior. +Telemetry uses the same local-state root for its anonymous identity file. It creates a PostHog client only when a project token is available and `DO_NOT_TRACK` is not `1`, and its capture helpers become no-ops when the client is unavailable [@telemetry]. Read [Telemetry](architecture/runtime/telemetry) with [Environment Variables](reference/configuration/environment-variables) before changing event capture, opt-out behavior, identity storage, release-build telemetry defaults, or shutdown behavior. ## Plugin, Tooling, And Checks -Rudder is packaged as `@ruddercode/rudder-plugin`, uses ESM, requires Node `>=23.6.0`, ships Claude Code and Codex plugin manifests, and builds a bundled prompt hook plus copied Drizzle migrations under `dist` [@package]. [Rudder Plugin Package](architecture/tooling/plugin-package) explains the plugin distribution surface; [Package Scripts](reference/tooling/package-scripts) and [TypeScript And Bundle Build](reference/tooling/typescript-build) give the exact command and compiler references. +Rudder is packaged as `@ruddercode/rudder-plugin`, uses ESM, requires Node `>=24.0.0`, ships Claude Code and Codex plugin manifests, and builds a bundled prompt hook plus copied Drizzle migrations under `dist` [@package]. [Rudder Plugin Package](architecture/tooling/plugin-package) explains the plugin distribution surface; [Package Scripts](reference/tooling/package-scripts) and [TypeScript And Bundle Build](reference/tooling/typescript-build) give the exact command and compiler references. For branch validation, start with [Run Checks](guides/contributor/run-checks). The local check flow verifies the centralized `.agents/skills` layout and agent attribution before running package commands, and the GitHub test workflow runs Node 24, `npm ci`, `npm run check:agent-layout`, `npm run format:markdown:check`, `npm run typecheck`, `npm test`, and `npm run build` on pushes and manual dispatch [@test-workflow]. [Contributor Automation](architecture/automation/contributor-automation), [Address PR Comments](guides/contributor/address-pr-comments), and [GitHub Workflows](reference/automation/github-workflows) cover the surrounding PR and automation surfaces. @@ -65,7 +65,7 @@ Release work starts from the plugin package version. The manifest stores the cur ## Product Intent -The README describes Rudder's product as intent-driven test generation: it uses prompts from the current coding-agent session plus worktree changes to generate focused unit tests, run repository test and coverage tools, and ask follow-up questions until a coverage target is reached [@readme]. Read [Intent-Driven Test Generation](concepts/product/intent-driven-test-generation), [Test Intent Standards](concepts/product/test-intent-standards), and [BYOK Skill Workflow](decisions/product/byok-skill-workflow) before making product-shaping changes. [Prompt History](concepts/runtime/prompt-history) is now implemented as local prompt capture that supplies branch-specific intent to the skill [@prompt-tagger] [@skill]. +The README describes Rudder's product as intent-driven test generation: it uses prompts from the current coding-agent session plus worktree changes to generate prompt-traceable unit tests through the user's existing agent and repository tooling [@readme]. Read [Intent-Driven Test Generation](concepts/product/intent-driven-test-generation), [Test Intent Standards](concepts/product/test-intent-standards), and [BYOK Skill Workflow](decisions/product/byok-skill-workflow) before making product-shaping changes. [Prompt History](concepts/runtime/prompt-history) is now implemented as local prompt capture that supplies branch-specific intent to the skill [@prompt-tagger] [@skill]. ## Common Starting Points @@ -74,7 +74,7 @@ The README describes Rudder's product as intent-driven test generation: it uses | Change package, tooling, automation, plugin, or runtime foundations | [Change Shared Infrastructure](guides/contributor/change-shared-infrastructure) | | Check protected agent paths or inline guards | [Protected Paths](reference/contributor/protected-paths) | | Work with local database state | [Local State](architecture/runtime/local-state) | -| Record, query, disable, or delete prompt capture data | [Use Prompt Capture](guides/runtime/use-prompt-capture) | +| Record, query, or delete prompt capture data | [Use Prompt Capture](guides/runtime/use-prompt-capture) | | Change the installed skill workflow or helper scripts | [Rudder Skill Runtime](architecture/runtime/rudder-skill-runtime) | | Change telemetry behavior | [Telemetry](architecture/runtime/telemetry) | | Validate a branch | [Run Checks](guides/contributor/run-checks) | diff --git a/almanac/guides/contributor/change-shared-infrastructure.md b/almanac/guides/contributor/change-shared-infrastructure.md index 0d51c77..043fdc3 100644 --- a/almanac/guides/contributor/change-shared-infrastructure.md +++ b/almanac/guides/contributor/change-shared-infrastructure.md @@ -21,9 +21,6 @@ sources: - id: prompt-tagger type: file path: src/prompt-tagger.ts - - id: prompt-control - type: file - path: src/prompt-control.ts - id: telemetry type: file path: src/telemetry.ts @@ -34,25 +31,25 @@ sources: # Change Shared Infrastructure -Use this guide when a task changes shared foundations rather than one isolated feature: package metadata or scripts, TypeScript compiler settings, GitHub automation, centralized agent workflows, generated database migrations, prompt capture, local state, plugin packaging, or telemetry lifecycle behavior [@package] [@tsconfig] [@db-client] [@prompt-tagger] [@prompt-control] [@telemetry]. The goal is to keep the change tied to the affected foundation, avoid [Protected Paths](../../reference/contributor/protected-paths), and finish with the repo's [Run Checks](run-checks) gate. +Use this guide when a task changes shared foundations rather than one isolated feature: package metadata or scripts, TypeScript compiler settings, GitHub automation, centralized agent workflows, generated database migrations, prompt capture, local state, plugin packaging, or telemetry lifecycle behavior [@package] [@tsconfig] [@db-client] [@prompt-tagger] [@telemetry]. The goal is to keep the change tied to the affected foundation, avoid [Protected Paths](../../reference/contributor/protected-paths), and finish with the repo's [Run Checks](run-checks) gate. ## Confirm The Surface -Start by naming the shared surface the task changes. Package work changes the manifest contract, dependency set, published file allowlist, bundled hook output, or npm script behavior [@package]. TypeScript work changes the shared NodeNext no-emit compiler model [@tsconfig]. Runtime-foundation work changes local database migration application, Rudder home resolution, dashboard port parsing, prompt capture, prompt data controls, or telemetry identity and PostHog client behavior [@db-client] [@prompt-tagger] [@prompt-control] [@telemetry]. +Start by naming the shared surface the task changes. Package work changes the manifest contract, dependency set, published file allowlist, bundled hook output, or npm script behavior [@package]. TypeScript work changes the shared NodeNext no-emit compiler model [@tsconfig]. Runtime-foundation work changes local database migration application, Rudder home resolution, dashboard port parsing, prompt capture, prompt data deletion, update-state caching, or telemetry identity and PostHog client behavior [@db-client] [@prompt-tagger] [@telemetry]. If the task is product behavior rather than shared infrastructure, use the product-intent, plugin, and runtime pages that describe that area instead of treating this guide as an approval gate. If the task does change a shared surface, continue with the protected-path check before editing. ## Check Protected Paths -Read `dangerfile.ts` before editing. The current protected path patterns are `README.md`, `LICENSE`, `CLAUDE.md`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` [@dangerfile]. +Read `dangerfile.ts` before editing. The current protected path patterns are `README.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `CLAUDE.md`, `docs/**`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` [@dangerfile]. Pull requests to `main` run the Danger workflow, which executes `npm run danger:ci` [@danger-workflow] [@package]. For agent-authored PRs, Danger fails changes to protected paths and changes inside inline `agent-guard:off` and `agent-guard:on` regions, while warning when policy files or guard markers change [@dangerfile]. Treat a protection relaxation as an intentional policy change, not a routine workaround; otherwise move the change to an unprotected path or ask the user for a different route. ## Make The Infrastructure Edit -Keep the edit inside the system area the task actually touches. For package or TypeScript changes, remember that the package manifest defines the validation commands, bundled hook output, and published file list, while `tsconfig.json` defines the no-emit source-checking globs [@package] [@tsconfig]. For runtime-foundation changes, keep persistent paths derived from `rudderHome()`, keep prompt capture aligned with the local data controls, and keep telemetry's opt-in client lifecycle aligned with the environment-variable contract [@db-client] [@prompt-control] [@telemetry]. +Keep the edit inside the system area the task actually touches. For package or TypeScript changes, remember that the package manifest defines the validation commands, bundled hook output, and published file list, while `tsconfig.json` defines the no-emit source-checking globs [@package] [@tsconfig]. For runtime-foundation changes, keep persistent paths derived from `rudderHome()`, keep prompt capture aligned with the local prompt-data deletion contract, and keep telemetry's client lifecycle aligned with the environment-variable contract [@db-client] [@prompt-tagger] [@telemetry]. -When an infrastructure change affects agent workflow behavior, consult [Run Checks](run-checks) for the centralized `.agents/skills` layout gate. Do not modify `CLAUDE.md`, `.claude/**`, `.codex/**`, or `.cursor/**` from an agent-authored PR because those paths are protected by Danger [@dangerfile]. +When an infrastructure change affects agent workflow behavior, consult [Run Checks](run-checks) for the centralized `.agents/skills` layout gate. Do not modify public docs, `CLAUDE.md`, `.claude/**`, `.codex/**`, or `.cursor/**` from an agent-authored PR because those paths are protected by Danger [@dangerfile]. ## Verify And Recover diff --git a/almanac/guides/release/prepare-package-release.md b/almanac/guides/release/prepare-package-release.md index 77916c8..509bb68 100644 --- a/almanac/guides/release/prepare-package-release.md +++ b/almanac/guides/release/prepare-package-release.md @@ -32,7 +32,7 @@ Also confirm that the package name remains exactly `@ruddercode/rudder-plugin`. ## Read The Release Alert -On PRs targeting `main`, the release-alert workflow checks whether npmjs.org already has the package version, whether the first publication would require the `NPM_TOKEN` bootstrap secret, whether the version's plugin tag exists, and whether a GitHub Release exists for the tag [@release-alert]. It posts or updates a sticky PR comment marked by ``, so repeated pushes update one comment instead of creating new release notices [@release-alert]. +On PRs targeting `main`, the release-alert workflow checks whether npmjs.org already has the package version, whether the version's plugin tag exists, and whether a GitHub Release exists for the tag [@release-alert]. It posts or updates a sticky PR comment marked by ``, so repeated pushes update one comment instead of creating new release notices [@release-alert]. If the alert says merge will release the plugin, verify that the named version and artifact targets are intentional. If it says no plugin release on merge, the current version already has the npm package, plugin tag, and GitHub Release; bump the version before merging if a new release is required [@release-alert]. @@ -40,7 +40,7 @@ If the alert says merge will release the plugin, verify that the named version a The publish workflow runs on pushes to `main` and on manual dispatch with concurrency group `publish-rudder-plugin` [@publish]. It reads the manifest version and package name, checks npmjs.org for that package version, checks whether the plugin tag exists, and checks whether the GitHub Release for the tag exists [@publish]. -If npmjs.org returns a missing-version response, npm publishing is enabled; if the package itself is also missing, bootstrap publishing requires `NPM_TOKEN`; if the tag or GitHub Release is missing, those artifacts are created [@publish]. When any release artifact is needed, the workflow installs Node 24, upgrades npm for Trusted Publishers support, runs `npm ci`, validates the package, publishes to npmjs.org when needed, pushes the tag when needed, and creates the GitHub Release with generated notes when needed [@publish]. +If npmjs.org returns a missing-version response, npm publishing is enabled; if the tag or GitHub Release is missing, those artifacts are created [@publish]. When any release artifact is needed, the workflow installs Node 24, upgrades npm for Trusted Publishers support, runs `npm ci`, writes release telemetry defaults into `src/telemetry-build-config.ts`, validates the package with telemetry disabled, publishes to npmjs.org when needed, pushes the tag when needed, and creates the GitHub Release with generated notes and title `Rudder v` when needed [@publish]. ## Recover From A Bad Alert diff --git a/almanac/guides/runtime/use-prompt-capture.md b/almanac/guides/runtime/use-prompt-capture.md index 81e5bc3..84429f3 100644 --- a/almanac/guides/runtime/use-prompt-capture.md +++ b/almanac/guides/runtime/use-prompt-capture.md @@ -1,6 +1,6 @@ --- title: "Use Prompt Capture" -summary: "Use prompt capture explains how runtime, hook, and skill code should store, query, disable, and delete Rudder's local prompt records." +summary: "Use prompt capture explains how runtime, hook, and skill code should store, query, and delete Rudder's local prompt records." topics: [guides, runtime, prompt-capture, prompt-history, database] sources: - id: db-client @@ -12,9 +12,9 @@ sources: - id: prompt-tagger type: file path: src/prompt-tagger.ts - - id: prompt-control + - id: transcript type: file - path: src/prompt-control.ts + path: src/transcript.ts - id: hook-bin type: file path: bin/rudder-prompt-hook.ts @@ -47,7 +47,7 @@ Installed plugin hooks also need the migration folder that ships inside the pack ## Record Hook Events -Use `recordPromptHookEvent(source, payload, fallbackCwd?)` for provider hook payloads. The helper supports `claude-code`, `codex`, and `cursor` sources, maps submit events to `recordPromptBranch()`, and maps `Stop` to `reconcilePromptBranch()` [@prompt-hook]. It returns `null` without writing when prompt capture is disabled [@prompt-hook] [@prompt-control]. +Use `recordPromptHookEvent(source, payload, fallbackCwd?)` for provider hook payloads. The helper supports `claude-code`, `codex`, and `cursor` sources, maps submit events to `recordPromptBranch()`, and maps `Stop` to `reconcilePromptBranch()` [@prompt-hook]. Submit payloads may include `transcript_path`; when present, Rudder reads the latest assistant text from the transcript and stores it as `previous_agent_output` if the transcript contains visible assistant output [@prompt-hook] [@transcript]. Use the executable path for plugin hook commands. `bin/rudder-prompt-hook.ts` reads JSON from stdin, infers the source from `PLUGIN_ROOT` or `CLAUDE_PLUGIN_ROOT` when a plugin host provides either variable, otherwise requires `--source `, and closes the database handle in `finally` [@hook-bin]. Tests enforce that both direct execution and plugin-host execution produce no stdout and ignore unavailable Git context without failing the host process [@hook-tests]. @@ -59,6 +59,6 @@ The skill treats those helper classifications as candidates. `skills/rudder/SKIL ## Respect Data Controls -Prompt capture can be disabled by setting `RUDDER_DISABLE_PROMPT_CAPTURE=1` or by creating the `prompt-capture-disabled` marker under the Rudder home directory [@prompt-control]. The `manage-data.mjs` helper reports status, writes or removes that marker for disable/enable, and deletes prompt rows only when invoked as `delete --confirm` [@data-script]. +The `manage-data.mjs` helper reports `rudderHome`, `databasePath`, and `promptCount`; it deletes prompt rows only when invoked as `delete --confirm` [@data-script]. It no longer accepts `disable` or `enable`, and the skill-runtime tests assert that `manage-data.mjs disable` fails with the usage contract [@skill-tests]. -Deletion is intentionally scoped to prompt records. `manage-data.mjs delete --confirm` counts rows in `prompt_branches`, enables SQLite secure deletion, deletes rows, truncates WAL, vacuums the database, and returns the remaining status [@data-script]. The skill-runtime tests enforce that an unconfirmed delete fails, confirmed deletion removes prompt records, and disable/enable toggles the capture preference [@skill-tests]. +Deletion is intentionally scoped to prompt records. `manage-data.mjs delete --confirm` counts rows in `prompt_branches`, enables SQLite secure deletion, deletes rows, truncates WAL, vacuums the database, and returns the remaining status [@data-script]. The skill-runtime tests enforce that an unconfirmed delete fails and confirmed deletion removes prompt records [@skill-tests]. diff --git a/almanac/reference/automation/github-workflows.md b/almanac/reference/automation/github-workflows.md index af94564..b096a11 100644 --- a/almanac/reference/automation/github-workflows.md +++ b/almanac/reference/automation/github-workflows.md @@ -39,16 +39,16 @@ The Test workflow runs one `test` job on `ubuntu-latest` [@test-workflow]. The j The Danger workflow runs one `danger` job on pull requests targeting `main` [@danger-workflow]. The job checks out full history, sets up Node 24, installs dependencies with `npm ci`, and runs `npm run danger:ci` with `GITHUB_TOKEN` [@danger-workflow]. -`dangerfile.ts` applies only when it detects agent authorship from the PR author, commit author names and emails, or `Co-authored-by` trailers [@dangerfile]. For detected-agent PRs, it fails changes to `README.md`, `LICENSE`, `CLAUDE.md`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**`; it also fails invalid inline agent guard markers and changes inside protected inline regions [@dangerfile]. Policy file changes and guard marker changes warn reviewers instead of silently changing the guard surface [@dangerfile]. +`dangerfile.ts` applies only when it detects agent authorship from the PR author, commit author names and emails, or `Co-authored-by` trailers [@dangerfile]. For detected-agent PRs, it fails changes to `README.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `CLAUDE.md`, `docs/**`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**`; it also fails invalid inline agent guard markers and changes inside protected inline regions [@dangerfile]. Policy file changes and guard marker changes warn reviewers instead of silently changing the guard surface [@dangerfile]. ## Publish Rudder Plugin The publish workflow serializes runs with concurrency group `publish-rudder-plugin` and does not cancel an in-progress publish [@publish-workflow]. The job checks out full history, reads `package.json` for `name` and `version`, derives `tag=rudder-plugin-v`, and fails if the package name is not exactly `@ruddercode/rudder-plugin` [@publish-workflow]. -The first step sets artifact flags. It checks npmjs.org with `npm view`, detects whether this is a first publication that needs `NPM_TOKEN`, checks the plugin tag with `git rev-parse`, and checks the GitHub Release through `gh api repos/${GITHUB_REPOSITORY}/releases/tags/${tag}` [@publish-workflow]. When any artifact is missing, the workflow sets up Node 24, installs the latest npm for Trusted Publishers support, runs `npm ci`, validates the plugin package, publishes to npmjs.org when needed, pushes the tag when needed, and creates the GitHub Release with generated notes when missing [@publish-workflow]. +The first step sets artifact flags. It checks npmjs.org with `npm view`, checks the plugin tag with `git rev-parse`, and checks the GitHub Release through `gh api repos/${GITHUB_REPOSITORY}/releases/tags/${tag}` [@publish-workflow]. When any artifact is missing, the workflow sets up Node 24, installs the latest npm for Trusted Publishers support, runs `npm ci`, writes release telemetry defaults from `POSTHOG_PROJECT_TOKEN` and `POSTHOG_HOST`, validates the plugin package with `DO_NOT_TRACK=1`, publishes to npmjs.org when needed, pushes the tag when needed, and creates the GitHub Release titled `Rudder v` with generated notes when missing [@publish-workflow]. ## Plugin Release Alert -The release-alert workflow uses concurrency group `plugin-release-alert-${{ github.event.pull_request.number }}` and cancels older in-progress runs for the same PR [@release-alert]. Its check step reads `package.json`, derives the same package fields as the publish workflow, rejects package names other than `@ruddercode/rudder-plugin`, checks npmjs.org with `npm view`, detects bootstrap-token need, checks the plugin tag, and checks the GitHub Release with `gh api` [@release-alert]. +The release-alert workflow uses concurrency group `plugin-release-alert-${{ github.event.pull_request.number }}` and cancels older in-progress runs for the same PR [@release-alert]. Its check step reads `package.json`, derives the same package fields as the publish workflow, rejects package names other than `@ruddercode/rudder-plugin`, checks npmjs.org with `npm view`, checks the plugin tag, and checks the GitHub Release with `gh api` [@release-alert]. -The comment step uses `actions/github-script@v7` with the hidden marker `` [@release-alert]. It updates the existing marked comment when present or creates a new comment, warning when merge will publish the plugin package, use the bootstrap token, create the plugin tag, or create the GitHub Release, and reporting no plugin release when all artifacts already exist for the version [@release-alert]. +The comment step uses `actions/github-script@v7` with the hidden marker `` [@release-alert]. It updates the existing marked comment when present or creates a new comment, warning when merge will publish the plugin package, create the plugin tag, or create the GitHub Release, and reporting no plugin release when all artifacts already exist for the version [@release-alert]. diff --git a/almanac/reference/configuration/environment-variables.md b/almanac/reference/configuration/environment-variables.md index 3228ea4..4a01153 100644 --- a/almanac/reference/configuration/environment-variables.md +++ b/almanac/reference/configuration/environment-variables.md @@ -1,20 +1,23 @@ --- title: "Environment Variables" -summary: "Rudder runtime configuration currently comes from environment variables covering local state, migration lookup, prompt capture, dashboard port selection, and telemetry." -topics: [reference, configuration, runtime, telemetry, prompt-capture] +summary: "Rudder runtime configuration currently comes from environment variables covering local state, migration lookup, dashboard port selection, telemetry, and update checks." +topics: [reference, configuration, runtime, telemetry] sources: - id: db-client type: file path: src/db/client.ts - - id: prompt-control - type: file - path: src/prompt-control.ts - id: telemetry type: file path: src/telemetry.ts + - id: telemetry-build-config + type: file + path: src/telemetry-build-config.ts + - id: update-script + type: file + path: skills/rudder/scripts/update.mjs --- -Rudder currently reads environment variables for local state location, migration lookup, prompt-capture disablement, dashboard port selection, and telemetry configuration. `RUDDER_HOME`, `RUDDER_MIGRATIONS_PATH`, and `RUDDER_PORT` are read by the database client module, `RUDDER_DISABLE_PROMPT_CAPTURE` is read by prompt controls, and `POSTHOG_API_KEY`, `POSTHOG_HOST`, and `DO_NOT_TRACK` control the PostHog telemetry client and opt-out behavior [@db-client] [@prompt-control] [@telemetry]. This reference lists the exact parsing and defaults used by those helpers; the surrounding runtime architecture is covered by [Local State](../../architecture/runtime/local-state), [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), and [Telemetry](../../architecture/runtime/telemetry). +Rudder currently reads environment variables for local state location, migration lookup, dashboard port selection, telemetry configuration, and update checks. `RUDDER_HOME`, `RUDDER_MIGRATIONS_PATH`, and `RUDDER_PORT` are read by the database client module; `POSTHOG_PROJECT_TOKEN`, `POSTHOG_API_KEY`, `POSTHOG_HOST`, and `DO_NOT_TRACK` control the PostHog telemetry client and opt-out behavior; `RUDDER_DISABLE_UPDATE_CHECK` disables skill update lookup [@db-client] [@telemetry] [@update-script]. This reference lists the exact parsing and defaults used by those helpers; the surrounding runtime architecture is covered by [Local State](../../architecture/runtime/local-state), [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), and [Telemetry](../../architecture/runtime/telemetry). ## Variables @@ -22,24 +25,21 @@ Rudder currently reads environment variables for local state location, migration | --- | --- | --- | --- | | `RUDDER_HOME` | `rudderHome()` | Any non-empty string path. | Empty or unset values fall back to `join(homedir(), '.rudder')` because the helper uses `process.env.RUDDER_HOME || ...` [@db-client]. | | `RUDDER_MIGRATIONS_PATH` | `migrationsFolder()` inside `openDb()` | Any string path, including an empty string. | Only `null` or `undefined` fall back to the repository `drizzle/` directory because the helper uses nullish coalescing [@db-client]. | -| `RUDDER_DISABLE_PROMPT_CAPTURE` | `promptCaptureDisabled()` | Exactly `1` disables prompt capture. | Any other value, including unset, does not disable capture by environment; the preference marker can still disable capture [@prompt-control]. | | `RUDDER_PORT` | `rudderPort()` | A value that `Number()` converts to an integer greater than `0` and less than `65536`. | Invalid, unset, fractional, zero, negative, or out-of-range values return `41789` [@db-client]. | -| `POSTHOG_API_KEY` | Telemetry module constant | Any non-empty string. | Empty or unset values disable client creation because `client()` returns `null` without an API key [@telemetry]. | -| `POSTHOG_HOST` | Telemetry module constant | Any non-empty string, passed to the PostHog client as `host`. | Empty or unset values use `https://us.i.posthog.com` [@telemetry]. | +| `POSTHOG_PROJECT_TOKEN` | Telemetry module constant | Any non-empty string. | Preferred telemetry token source; empty or unset values fall back to `POSTHOG_API_KEY`, then the built-in release-build token [@telemetry] [@telemetry-build-config]. | +| `POSTHOG_API_KEY` | Telemetry module constant | Any non-empty string. | Legacy telemetry token source used only when `POSTHOG_PROJECT_TOKEN` is unset or empty [@telemetry]. | +| `POSTHOG_HOST` | Telemetry module constant | Any non-empty string, passed to the PostHog client as `host`. | Empty or unset values fall back to the built-in release-build host, then `https://us.i.posthog.com` [@telemetry] [@telemetry-build-config]. | | `DO_NOT_TRACK` | `telemetryDisabled()` | Exactly `1` disables telemetry. | Any other value, including unset, does not disable telemetry by itself [@telemetry]. | +| `RUDDER_DISABLE_UPDATE_CHECK` | `checkForUpdate()` | Exactly `1` disables registry update lookup. | Any other value, including unset, allows `scripts/update.mjs check` to use fresh cache or query npm [@update-script]. | ## Read Timing -`RUDDER_HOME` is read each time `rudderHome()` runs, `RUDDER_MIGRATIONS_PATH` is read when `openDb()` applies migrations, and `RUDDER_PORT` is read each time `rudderPort()` runs [@db-client]. `promptCaptureDisabled()` reads `RUDDER_DISABLE_PROMPT_CAPTURE` from the environment object passed to it, defaulting to `process.env` [@prompt-control]. By contrast, `POSTHOG_API_KEY` and `POSTHOG_HOST` are assigned to module-level constants when `src/telemetry.ts` is evaluated [@telemetry]. `telemetryDisabled()` defaults to `process.env` but also accepts an explicit environment object, which makes the `DO_NOT_TRACK` check callable against injected values [@telemetry]. +`RUDDER_HOME` is read each time `rudderHome()` runs, `RUDDER_MIGRATIONS_PATH` is read when `openDb()` applies migrations, and `RUDDER_PORT` is read each time `rudderPort()` runs [@db-client]. `POSTHOG_PROJECT_TOKEN`, `POSTHOG_API_KEY`, and `POSTHOG_HOST` are assigned to module-level constants when `src/telemetry.ts` is evaluated [@telemetry]. `telemetryDisabled()` defaults to `process.env` but also accepts an explicit environment object, which makes the `DO_NOT_TRACK` check callable against injected values [@telemetry]. `RUDDER_DISABLE_UPDATE_CHECK` is read when `checkForUpdate()` runs [@update-script]. ## State Paths -When `RUDDER_HOME` is unset, the runtime state root is `~/.rudder`; when it is set to a non-empty value, that value becomes the state root [@db-client]. The SQLite database path is always `/rudder.db`, and the prompt-capture preference marker is `/prompt-capture-disabled` [@db-client] [@prompt-control]. Telemetry identity uses the same state root and stores the anonymous id at `/identity.json` [@telemetry]. Developers using [Use Prompt Capture](../../guides/runtime/use-prompt-capture) should set `RUDDER_HOME` before opening the database when they need isolated local state. - -## Prompt Capture Disablement - -Prompt capture is disabled when `RUDDER_DISABLE_PROMPT_CAPTURE === '1'` or when the preference marker exists [@prompt-control]. `setPromptCaptureEnabled(false)` creates the marker, and `setPromptCaptureEnabled(true)` removes it, but removing the marker does not override the environment variable [@prompt-control]. +When `RUDDER_HOME` is unset, the runtime state root is `~/.rudder`; when it is set to a non-empty value, that value becomes the state root [@db-client]. The SQLite database path is always `/rudder.db` [@db-client]. Telemetry identity uses the same state root and stores the anonymous id at `/identity.json` [@telemetry]. The update helper stores its cache at `/update-state.json` [@update-script]. Developers using [Use Prompt Capture](../../guides/runtime/use-prompt-capture) should set `RUDDER_HOME` before opening the database when they need isolated local state. ## Telemetry Disablement -Telemetry requires both an API key and an enabled client path. The internal client factory returns `null` when `POSTHOG_API_KEY` is empty or `telemetryDisabled()` returns true [@telemetry]. Because `telemetryDisabled()` checks only `DO_NOT_TRACK === '1'`, values such as `true`, `yes`, `0`, or an empty string do not disable telemetry through that helper [@telemetry]. +Telemetry requires both a project token and an enabled client path. The internal client factory returns `null` when the selected token is empty or `telemetryDisabled()` returns true [@telemetry]. Because `telemetryDisabled()` checks only `DO_NOT_TRACK === '1'`, values such as `true`, `yes`, `0`, or an empty string do not disable telemetry through that helper [@telemetry]. diff --git a/almanac/reference/contributor/protected-paths.md b/almanac/reference/contributor/protected-paths.md index afb7849..ffe24ed 100644 --- a/almanac/reference/contributor/protected-paths.md +++ b/almanac/reference/contributor/protected-paths.md @@ -11,15 +11,18 @@ sources: path: .github/workflows/danger.yml --- -Agent-protected paths are repository paths matched by `PROTECTED_PATHS` in `dangerfile.ts` and evaluated by Danger when a pull request has detected agent authorship. The current protected patterns are `README.md`, `LICENSE`, `CLAUDE.md`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` [@dangerfile]. CI detects agent authorship from the PR author, commit author names and emails, and `Co-authored-by` trailers; when no agent identity is detected, the scheduled Danger check returns before enforcing path or inline guards [@dangerfile]. +Agent-protected paths are repository paths matched by `PROTECTED_PATHS` in `dangerfile.ts` and evaluated by Danger when a pull request has detected agent authorship. The current protected patterns are `README.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `CLAUDE.md`, `docs/**`, `assets/**`, `.claude/**`, `.codex/**`, and `.cursor/**` [@dangerfile]. CI detects agent authorship from the PR author, commit author names and emails, and `Co-authored-by` trailers; when no agent identity is detected, the scheduled Danger check returns before enforcing path or inline guards [@dangerfile]. ## Current Rules | Pattern | Scope | | --- | --- | | `README.md` | Protects the root README file [@dangerfile]. | +| `CONTRIBUTING.md` | Protects the contributor guide [@dangerfile]. | +| `CODE_OF_CONDUCT.md` | Protects the code of conduct [@dangerfile]. | | `LICENSE` | Protects the root license file [@dangerfile]. | | `CLAUDE.md` | Protects the root Claude instruction handoff file [@dangerfile]. | +| `docs/**` | Protects public documentation under `docs/` [@dangerfile]. | | `assets/**` | Protects root assets and paths beneath them [@dangerfile]. | | `.claude/**` | Protects Claude compatibility files and symlinks [@dangerfile]. | | `.codex/**` | Protects Codex compatibility files and symlinks [@dangerfile]. | diff --git a/almanac/reference/database/prompt-branches-schema.md b/almanac/reference/database/prompt-branches-schema.md index 16fc99a..26e92f0 100644 --- a/almanac/reference/database/prompt-branches-schema.md +++ b/almanac/reference/database/prompt-branches-schema.md @@ -1,6 +1,6 @@ --- title: "Prompt Branches Schema" -summary: "The prompt branches schema reference defines Rudder's local prompt table, Drizzle declaration, migration, indexes, hook normalization, and helper contracts." +summary: "The prompt branches schema reference defines Rudder's local prompt table, Drizzle declaration, migrations, indexes, hook normalization, and helper contracts." topics: [reference, database, prompt-capture, prompt-history, runtime, sqlite] sources: - id: schema @@ -9,6 +9,9 @@ sources: - id: prompt-migration type: file path: drizzle/20260722200723_prompt-branch-links/migration.sql + - id: previous-output-migration + type: file + path: drizzle/20260723191552_capture-previous-agent-output/migration.sql - id: db-client type: file path: src/db/client.ts @@ -18,9 +21,6 @@ sources: - id: prompt-hook type: file path: src/prompt-hook.ts - - id: prompt-control - type: file - path: src/prompt-control.ts - id: migrations-test type: file path: test/migrations.test.ts @@ -31,11 +31,11 @@ sources: # Prompt Branches Schema -The `prompt_branches` table is Rudder's SQLite storage contract for captured prompt intent. Drizzle declares the table in `src/db/schema.ts`, the generated migration under `drizzle/` creates it at runtime, and `src/prompt-tagger.ts` defines the write, reconciliation, and lookup helper contracts [@schema] [@prompt-migration] [@prompt-tagger]. This reference is the exact lookup companion to [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt History](../../concepts/runtime/prompt-history), and the [generated migrations decision](../../decisions/database/generated-drizzle-migrations). +The `prompt_branches` table is Rudder's SQLite storage contract for captured prompt intent. Drizzle declares the table in `src/db/schema.ts`, generated migrations under `drizzle/` create and extend it at runtime, and `src/prompt-tagger.ts` defines the write, reconciliation, and lookup helper contracts [@schema] [@prompt-migration] [@previous-output-migration] [@prompt-tagger]. This reference is the exact lookup companion to [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt History](../../concepts/runtime/prompt-history), and the [generated migrations decision](../../decisions/database/generated-drizzle-migrations). ## Runtime Creation -`openDb()` enables WAL, sets `PRAGMA busy_timeout = 5000`, enables `PRAGMA secure_delete = ON`, constructs a Drizzle client over the same `DatabaseSync` handle, and runs `migrate(orm, { migrationsFolder })` before caching the handles [@db-client]. The migration test opens a new database and asserts that `prompt_branches` is the live prompt/session table and that Drizzle recorded two applied migrations [@migrations-test]. +`openDb()` enables WAL, sets `PRAGMA busy_timeout = 5000`, enables `PRAGMA secure_delete = ON`, constructs a Drizzle client over the same `DatabaseSync` handle, and runs `migrate(orm, { migrationsFolder })` before caching the handles [@db-client]. The migration test opens a new database, asserts that `prompt_branches` is the live prompt/session table, verifies nullable `previous_agent_output`, and asserts that Drizzle recorded three applied migrations [@migrations-test]. ## Columns @@ -45,6 +45,7 @@ The `prompt_branches` table is Rudder's SQLite storage contract for captured pro | `session_id` | `text NOT NULL` [@prompt-migration] | `sessionId: text('session_id').notNull()` [@schema] | Trimmed nonblank agent session ID [@prompt-hook] [@prompt-tagger]. | | `prompt_id` | `text NOT NULL` [@prompt-migration] | `promptId: text('prompt_id').notNull()` [@schema] | Provider prompt key or generated UUID when missing [@prompt-hook] [@prompt-tagger]. | | `prompt_text` | `text NOT NULL` [@prompt-migration] | `promptText: text('prompt_text').notNull()` [@schema] | Submitted prompt text; blank text is rejected [@prompt-tagger]. | +| `previous_agent_output` | `text` added by `20260723191552_capture-previous-agent-output` [@previous-output-migration] | `previousAgentOutput: text('previous_agent_output')` [@schema] | Optional latest assistant output read from hook `transcript_path`; blank output is stored as `null` [@prompt-hook] [@prompt-tagger]. | | `repository` | `text NOT NULL` [@prompt-migration] | `text('repository').notNull()` [@schema] | Normalized repository key [@prompt-tagger]. | | `branch` | `text NOT NULL` [@prompt-migration] | `text('branch').notNull()` [@schema] | Normalized branch name [@prompt-tagger]. | | `submitted_at` | `text NOT NULL` [@prompt-migration] | `submittedAt: text('submitted_at').notNull()` [@schema] | ISO submission timestamp [@prompt-tagger]. | @@ -70,10 +71,8 @@ The hook normalizer also accepts `Stop` as reconciliation, uses `cwd` when prese ## Helper Contracts -`recordPromptBranch(input)` records a submitted prompt and returns the stored row. Replaying the same source/session/prompt ID updates prompt text and keeps the earliest submission time [@prompt-tagger] [@prompt-tests]. +`recordPromptBranch(input)` records a submitted prompt and returns the stored row. Replaying the same source/session/prompt ID updates prompt text, keeps the earliest submission time, and preserves the first non-null previous agent output [@prompt-tagger] [@prompt-tests]. `reconcilePromptBranch(input)` updates a submitted prompt to the branch active after the agent turn. If the input omits a prompt ID, it reconciles the latest unreconciled prompt for the same source/session pair [@prompt-tagger] [@prompt-tests]. `promptsForSession(source, sessionId)` returns prompts ordered by `submittedAt` and `promptId` [@prompt-tagger]. `promptsForBranch(repository, branch)` normalizes repository and branch input, then returns branch prompts ordered by submission time, source, session ID, and prompt ID [@prompt-tagger]. - -`promptCaptureDisabled()` disables writes when `RUDDER_DISABLE_PROMPT_CAPTURE` is `1` or when the preference marker exists under the Rudder home directory [@prompt-control]. diff --git a/almanac/reference/tooling/package-scripts.md b/almanac/reference/tooling/package-scripts.md index 1304cdb..83c646b 100644 --- a/almanac/reference/tooling/package-scripts.md +++ b/almanac/reference/tooling/package-scripts.md @@ -29,7 +29,7 @@ This reference lists the npm scripts defined by Rudder's package and the local o | `danger:ci` | `danger ci --failOnErrors` | Runs Danger with failing errors for CI agent-guard enforcement [@package-json]. | | `check:agent-layout` | `test -L .claude/skills && test -L .codex/skills && test .claude/skills -ef .agents/skills && test .codex/skills -ef .agents/skills && test ! -e .claude/commands && grep -Fxq '@AGENTS.md' CLAUDE.md` | Verifies Claude/Codex skill symlinks, absence of Claude command aliases, and the `CLAUDE.md` handoff [@package-json]. | | `typecheck` | `tsc --noEmit` | Runs TypeScript checking without writing build output [@package-json]. | -| `build` | `rm -rf dist && esbuild bin/rudder-prompt-hook.ts --bundle --platform=node --format=esm --target=node23 --outfile=dist/rudder-prompt-hook.mjs && cp -R drizzle dist/drizzle` | Removes old `dist` output, bundles the prompt hook for Node ESM, then copies generated Drizzle migrations into the package build tree [@package-json]. | +| `build` | `rm -rf dist && esbuild bin/rudder-prompt-hook.ts --bundle --platform=node --format=esm --target=node24 --outfile=dist/rudder-prompt-hook.mjs && cp -R drizzle dist/drizzle` | Removes old `dist` output, bundles the prompt hook for Node ESM, then copies generated Drizzle migrations into the package build tree [@package-json]. | | `pretest` | `npm run build` | Rebuilds the hook bundle before tests [@package-json]. | | `test` | `node --test` | Runs Node's built-in test runner [@package-json]. | | `prepack` | `npm run build` | Rebuilds package artifacts before `npm pack` [@package-json]. | diff --git a/almanac/reference/tooling/typescript-build.md b/almanac/reference/tooling/typescript-build.md index b018774..c78b32e 100644 --- a/almanac/reference/tooling/typescript-build.md +++ b/almanac/reference/tooling/typescript-build.md @@ -14,14 +14,14 @@ sources: path: bin/rudder-prompt-hook.ts --- -This reference defines Rudder's current TypeScript and bundle contract. `tsconfig.json` is a strict, no-emit NodeNext setup for `bin/**/*.ts`, `dangerfile.ts`, and `src/**/*.ts`; `npm run build` uses esbuild to bundle `bin/rudder-prompt-hook.ts` into `dist/rudder-prompt-hook.mjs` and then copies `drizzle/` into `dist/drizzle` [@tsconfig] [@package-json] [@hook-bin]. The package manifest declares the package as ESM, requires Node `>=23.6.0`, and wires `typecheck`, `build`, `pretest`, `prepack`, and `prepublishOnly` to that contract [@package-json]. +This reference defines Rudder's current TypeScript and bundle contract. `tsconfig.json` is a strict, no-emit NodeNext setup for `bin/**/*.ts`, `dangerfile.ts`, and `src/**/*.ts`; `npm run build` uses esbuild to bundle `bin/rudder-prompt-hook.ts` into `dist/rudder-prompt-hook.mjs` and then copies `drizzle/` into `dist/drizzle` [@tsconfig] [@package-json] [@hook-bin]. The package manifest declares the package as ESM, requires Node `>=24.0.0`, and wires `typecheck`, `build`, `pretest`, `prepack`, and `prepublishOnly` to that contract [@package-json]. ## Package Context | Field | Value | | --- | --- | | Package module type | `"module"` [@package-json] | -| Node engine | `>=23.6.0` [@package-json] | +| Node engine | `>=24.0.0` [@package-json] | | Package entrypoint | No `main` or `exports` entry is declared; plugin hosts load artifacts through manifest and hook configuration [@package-json]. | | Type entrypoint | No package `types` entry is declared [@package-json]. | | TypeScript dev dependency | `^5.7.0` [@package-json] | @@ -52,7 +52,7 @@ The NodeNext settings make the compiler follow Node's ESM-aware module rules, wh ## Bundle Output -The repository no longer has a `tsconfig.build.json` overlay. Build output is generated by esbuild from `bin/rudder-prompt-hook.ts` with `--bundle`, `--platform=node`, `--format=esm`, `--target=node23`, and `--outfile=dist/rudder-prompt-hook.mjs` [@package-json] [@hook-bin]. The build then copies `drizzle/` into `dist/drizzle` so the installed prompt hook can point migration lookup at packaged migration files [@package-json]. +The repository no longer has a `tsconfig.build.json` overlay. Build output is generated by esbuild from `bin/rudder-prompt-hook.ts` with `--bundle`, `--platform=node`, `--format=esm`, `--target=node24`, and `--outfile=dist/rudder-prompt-hook.mjs` [@package-json] [@hook-bin]. The build then copies `drizzle/` into `dist/drizzle` so the installed prompt hook can point migration lookup at packaged migration files [@package-json]. ## Included Sources From 33c3471db2b62e68f9226154e29ea0d5f5b8f6ce Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Wed, 29 Jul 2026 17:47:34 -0400 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9D=20Garden=20Almanac=20maintenan?= =?UTF-8?q?ce=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../release/release-automation.md | 2 +- .../runtime/prompt-branch-store.md | 5 ++++- .../runtime/rudder-skill-runtime.md | 2 +- .../architecture/tooling/package-baseline.md | 2 +- .../architecture/tooling/plugin-package.md | 2 +- almanac/concepts/runtime/prompt-history.md | 2 +- .../reference/wiki/codealmanac-maintenance.md | 20 +++++++++++++------ 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/almanac/architecture/release/release-automation.md b/almanac/architecture/release/release-automation.md index 24205ee..c7766b5 100644 --- a/almanac/architecture/release/release-automation.md +++ b/almanac/architecture/release/release-automation.md @@ -18,7 +18,7 @@ Rudder's release automation is split between a publishing workflow on `main` and ## Version As Release Input -`package.json` is the only version input for the workflows. The package is currently `@ruddercode/rudder-plugin` at version `0.1.3`, and both workflows turn that version into tag `rudder-plugin-v0.1.3` at runtime [@package-json] [@publish-workflow] [@release-alert]. The release-alert workflow performs the same package-name, version, tag, npm, and GitHub Release checks on pull requests to `main` [@release-alert]. +`package.json` is the only version input for the workflows. Both workflows read the manifest version at runtime and turn it into tag `rudder-plugin-v` [@package-json] [@publish-workflow] [@release-alert]. The release-alert workflow performs the same package-name, version, tag, npm, and GitHub Release checks on pull requests to `main` [@release-alert]. Both workflows reject any package name other than `@ruddercode/rudder-plugin` before attempting release work [@publish-workflow] [@release-alert]. This is a release invariant: changing the package name affects plugin marketplace metadata, npm publication, and tag naming, so evaluate it through [Prepare Package Release](../../guides/release/prepare-package-release) and [Rudder Plugin Package](../tooling/plugin-package). diff --git a/almanac/architecture/runtime/prompt-branch-store.md b/almanac/architecture/runtime/prompt-branch-store.md index 48caf94..f0483d3 100644 --- a/almanac/architecture/runtime/prompt-branch-store.md +++ b/almanac/architecture/runtime/prompt-branch-store.md @@ -33,6 +33,9 @@ sources: - id: hook-tests type: file path: test/prompt-hook.test.ts + - id: data-script + type: file + path: skills/rudder/scripts/manage-data.mjs - id: skill-tests type: file path: test/skill-runtime.test.ts @@ -58,7 +61,7 @@ On submit, `recordPromptBranch()` resolves the current repository and branch, va The read paths are `promptsForSession(source, sessionId)` and `promptsForBranch(repository, branch)` [@prompt-tagger]. Session lookup orders prompts by submission time and prompt ID, while branch lookup normalizes repository and branch input before ordering by submission time, source, session ID, and prompt ID [@prompt-tagger]. -Prompt capture is optional metadata, but the current write path has no prompt-capture disable check. The skill-runtime tests leave a legacy `prompt-capture-disabled` marker in the Rudder home directory and set `RUDDER_DISABLE_PROMPT_CAPTURE=1`, then verify that `recordPromptHookEvent()` still stores the prompt [@skill-tests]. +Prompt capture is best-effort hook metadata, not a mode that data controls can disable. The current write path has no prompt-capture disable check: skill-runtime tests leave a legacy `prompt-capture-disabled` marker in the Rudder home directory and set `RUDDER_DISABLE_PROMPT_CAPTURE=1`, then verify that `recordPromptHookEvent()` still stores the prompt [@skill-tests]. Current data controls are status lookup and confirmed prompt-row deletion through `manage-data.mjs`; they do not include enable or disable commands [@data-script] [@skill-tests]. ## Failure Boundary diff --git a/almanac/architecture/runtime/rudder-skill-runtime.md b/almanac/architecture/runtime/rudder-skill-runtime.md index 5ed5001..c3a83cc 100644 --- a/almanac/architecture/runtime/rudder-skill-runtime.md +++ b/almanac/architecture/runtime/rudder-skill-runtime.md @@ -38,7 +38,7 @@ When a user accepts an update notice, the skill runs `scripts/update.mjs apply - ## Context Helper -`scripts/context.mjs` resolves the repository root from `--cwd`, requires an attached Git branch, chooses a base ref from `--base` or common `origin/main` and `master` fallbacks, calculates the merge base, and returns changed tracked and untracked paths as JSON [@context-script]. It classifies likely test paths using directory and filename conventions, leaves all other changed paths in `otherPaths`, normalizes the repository key from the active branch remote or a hashed local Git common directory, and reads matching prompts from `prompt_branches` in the local Rudder database when that table exists [@context-script]. +`scripts/context.mjs` resolves the repository root from `--cwd`, requires an attached Git branch, chooses a base ref from `--base` or common `origin/main` and `master` fallbacks, calculates the merge base, and returns changed tracked and untracked paths as JSON [@context-script]. It classifies likely test paths using directory and filename conventions, leaves all other changed paths in `otherPaths`, normalizes the repository key from the active branch remote or a hashed local Git common directory, and reads matching prompts from `prompt_branches` in the local Rudder database when that table exists [@context-script]. The prompt objects returned to the skill include identifiers, prompt text, and timestamps; they do not currently include stored previous agent output [@context-script]. The skill treats this JSON as input, not as final judgment. It instructs the agent to inspect the merge base, changed paths, captured prompts, repository instructions, production diff, existing tests, and native test/coverage configuration before deciding which test changes matter [@skill]. diff --git a/almanac/architecture/tooling/package-baseline.md b/almanac/architecture/tooling/package-baseline.md index 9675c21..31fcbfc 100644 --- a/almanac/architecture/tooling/package-baseline.md +++ b/almanac/architecture/tooling/package-baseline.md @@ -24,7 +24,7 @@ Rudder's package baseline is the repo's build and distribution frame for the plu ## Package Contract -`package.json` is the public package contract. It names the package, version `0.1.3`, Apache-2.0 license, GitHub repository metadata, supported Node engine, package scripts, and package file allowlist [@package-json]. The manifest intentionally carries plugin artifacts rather than a `main`, `types`, or package-root `exports` entry; plugin hosts load the installed hook through `hooks/hooks.json`, and tests enforce that the manifest does not define runtime dependencies or npm workspaces [@package-json] [@plugin-tests]. +`package.json` is the public package contract. It names the package, carries the current release version, declares the Apache-2.0 license and GitHub repository metadata, sets the supported Node engine, and defines package scripts plus the package file allowlist [@package-json]. The manifest intentionally carries plugin artifacts rather than a `main`, `types`, or package-root `exports` entry; plugin hosts load the installed hook through `hooks/hooks.json`, and tests enforce that the manifest does not define runtime dependencies or npm workspaces [@package-json] [@plugin-tests]. The package file allowlist keeps distribution narrow but plugin-complete. `.claude-plugin`, `.codex-plugin`, `assets`, `docs`, `hooks`, `skills`, `dist`, and `LICENSE` ship with the package [@package-json]. Build output and transient development files are excluded from the working tree by `.gitignore`, which ignores `node_modules/`, `dist/`, TypeScript build info, logs, `.env` files except `.env.example`, coverage, and common editor files [@gitignore]. diff --git a/almanac/architecture/tooling/plugin-package.md b/almanac/architecture/tooling/plugin-package.md index 27b1963..001d650 100644 --- a/almanac/architecture/tooling/plugin-package.md +++ b/almanac/architecture/tooling/plugin-package.md @@ -43,7 +43,7 @@ The repository root is the publishable Rudder plugin package. `package.json` nam The Claude manifest and Codex manifest share the public plugin name `rudder`, version, description, license, repository, keywords, and `./skills/` path [@claude-manifest] [@codex-manifest]. The Claude manifest also points at `./hooks/hooks.json`, while the Codex manifest carries interface metadata such as display name, short description, category, default prompt, icon, logo, privacy URL, and terms URL [@claude-manifest] [@codex-manifest]. -The marketplace catalog under `.claude-plugin/marketplace.json` lists one plugin named `rudder` and resolves it from npm package `@ruddercode/rudder-plugin` version `0.1.3` on the public npm registry [@marketplace]. Tests enforce that the package version is synchronized across `package.json`, `package-lock.json`, both plugin manifests, and both marketplace version fields [@plugin-tests]. The install docs describe Claude Code and Codex marketplace installation separately but state that both use the same npm-backed plugin package [@install-doc]. +The marketplace catalog under `.claude-plugin/marketplace.json` lists one plugin named `rudder` and resolves it from npm package `@ruddercode/rudder-plugin` on the public npm registry [@marketplace]. Tests enforce that the package version is synchronized across `package.json`, `package-lock.json`, both plugin manifests, and both marketplace version fields [@plugin-tests]. The install docs describe Claude Code and Codex marketplace installation separately but state that both use the same npm-backed plugin package [@install-doc]. ## Bundled Hook diff --git a/almanac/concepts/runtime/prompt-history.md b/almanac/concepts/runtime/prompt-history.md index 50acbe8..d08f34b 100644 --- a/almanac/concepts/runtime/prompt-history.md +++ b/almanac/concepts/runtime/prompt-history.md @@ -41,4 +41,4 @@ Prompt capture starts from coding-agent hooks. `recordPromptHookEvent()` normali ## Working Implication -When updating the product workflow, treat prompt history as local and branch-scoped. `skills/rudder/scripts/context.mjs` reads prompt identifiers, text, and timestamps for the resolved repository and branch from `prompt_branches` and returns them beside the branch diff, so the skill can combine implementation changes with user-stated intent [@context-script]. Use [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt Branches Schema](../../reference/database/prompt-branches-schema), and [Use Prompt Capture](../../guides/runtime/use-prompt-capture) for current implementation work. +When updating the product workflow, treat prompt history as local and branch-scoped. `skills/rudder/scripts/context.mjs` reads prompt identifiers, text, and timestamps for the resolved repository and branch from `prompt_branches` and returns them beside the branch diff, so the skill can combine implementation changes with user-stated intent [@context-script]. The table can store `previous_agent_output`, but the current context helper does not include that field in the skill JSON; using previous agent output in `$rudder` requires changing the helper and its tests, not just reading the stored rows [@schema] [@context-script]. Use [Prompt Branch Store](../../architecture/runtime/prompt-branch-store), [Prompt Branches Schema](../../reference/database/prompt-branches-schema), and [Use Prompt Capture](../../guides/runtime/use-prompt-capture) for current implementation work. diff --git a/almanac/reference/wiki/codealmanac-maintenance.md b/almanac/reference/wiki/codealmanac-maintenance.md index 7b53882..ed0bc02 100644 --- a/almanac/reference/wiki/codealmanac-maintenance.md +++ b/almanac/reference/wiki/codealmanac-maintenance.md @@ -1,12 +1,16 @@ --- title: "CodeAlmanac Maintenance" -summary: "This reference records Rudder's local CodeAlmanac maintenance mode: scheduled sync and garden are enabled, auto-commit is allowed for wiki source changes, and package update automation remains disabled." +summary: "This reference records how to verify Rudder's local CodeAlmanac maintenance state, with dated snapshots for scheduled automation and the wiki-source commit boundary." topics: [reference, wiki, automation] sources: - id: automation-session type: conversation path: /Users/vivek/.codex/sessions/2026/07/22/rollout-2026-07-22T11-37-04-019f8a79-2786-7200-bc5f-4d94980ab0fc.jsonl title: "CodeAlmanac automation setup transcript" + - id: live-garden-snapshot + type: conversation + path: /Users/vivek/.codex/sessions/2026/07/29/rollout-2026-07-29T17-12-22-019fafb8-a3c6-7f11-9b38-0b5430c6ce08.jsonl + title: "CodeAlmanac Garden live-state transcript" - id: ingest-manual type: manual path: ingest.md @@ -21,15 +25,19 @@ sources: title: "Sources manual" --- -CodeAlmanac maintenance for Rudder is configured as a local scheduled workflow, not a per-PR documentation requirement. As of July 22, 2026, transcript sync and garden automation are enabled, package update automation is disabled, telemetry is disabled, and `auto_commit` is enabled so CodeAlmanac may commit its own wiki-source changes [@automation-session]. Because this is user-scoped runtime configuration, verify the live state with `codealmanac config list` and `codealmanac automation status` before depending on it [@automation-session]. For broader repository routing, use [Getting Started](../../getting-started). +CodeAlmanac maintenance for Rudder is user-scoped local automation, not a per-PR documentation requirement. Treat this page as a verification reference: run `codealmanac config list` and `codealmanac automation status` in the repository before depending on telemetry, scheduled jobs, or `auto_commit`, because those settings live outside the committed wiki source [@automation-session] [@live-garden-snapshot]. For broader repository routing, use [Getting Started](../../getting-started). + +## Verify Live State + +Start with `codealmanac config list`. Check `telemetry.enabled`, `auto_commit`, `automation.sync.enabled`, `automation.garden.enabled`, `automation.update.enabled`, and the matching `*.every` intervals before describing local maintenance state as current [@live-garden-snapshot]. -## Scheduled Jobs +Then run `codealmanac automation status`. Check whether the sync, garden, and update LaunchAgents are installed, loaded, idle or running, and whether their last result succeeded [@live-garden-snapshot]. The current LaunchAgent paths use `/Users/vivek/Library/LaunchAgents/com.codealmanac.sync.plist`, `com.codealmanac.garden.plist`, and `com.codealmanac.update.plist` when installed [@live-garden-snapshot]. -Transcript sync is enabled with `automation.sync.every` set to `5h`. The setup run installed and loaded `/Users/vivek/Library/LaunchAgents/com.codealmanac.sync.plist`, and its first reported run succeeded [@automation-session]. +## Dated Snapshots -Garden is enabled with `automation.garden.every` set to `24h`. The setup run installed and loaded `/Users/vivek/Library/LaunchAgents/com.codealmanac.garden.plist`, and its first reported run succeeded [@automation-session]. +On July 22, 2026, the setup transcript recorded transcript sync and garden automation as enabled, update automation as not installed, telemetry as disabled, and `auto_commit` as enabled [@automation-session]. That snapshot is historical evidence, not a standing claim about the user's current machine state. -Update automation remains disabled even though the update interval setting exists at `24h`. The setup run reported `update automation: not installed`, so scheduled CLI package updates are outside the current maintenance mode [@automation-session]. +On July 29, 2026, a Garden run observed `telemetry.enabled true`, `automation.sync.enabled true`, `automation.garden.enabled true`, `automation.update.enabled true`, and `auto_commit true`; `codealmanac automation status` also reported sync, garden, and update automation installed, loaded, idle, and last succeeded [@live-garden-snapshot]. ## Commit Boundary