diff --git a/.claude/skills b/.claude/skills
new file mode 120000
index 0000000000..42c5394a18
--- /dev/null
+++ b/.claude/skills
@@ -0,0 +1 @@
+../skills
\ No newline at end of file
diff --git a/.github/workflows/ai_explain.py b/.github/workflows/ai_explain.py
deleted file mode 100644
index 4aa79fa985..0000000000
--- a/.github/workflows/ai_explain.py
+++ /dev/null
@@ -1,125 +0,0 @@
-import json
-import os
-import sys
-
-from github import Github
-from openai import APIConnectionError, OpenAI, OpenAIError
-
-
-# Initialize GitHub and OpenAI clients
-github_token = os.getenv("GITHUB_TOKEN")
-repo_name = os.getenv("GITHUB_REPOSITORY")
-pr_ref = os.getenv("GITHUB_REF")
-
-# Extract PR number from the ref (refs/pull/{pr_number}/merge)
-pr_number = pr_ref.split("/")[2]
-
-g = Github(github_token)
-repo = g.get_repo(repo_name)
-pr = repo.get_pull(int(pr_number))
-
-# Get the files changed in the current PR
-files = pr.get_files()
-diffs = []
-
-for file in files:
- filename = file.filename
- patch = file.patch
- diffs.append(f"File: {filename}\n{patch}")
-
-diff = "\n\n".join(diffs)
-
-# Add a unique marker at the start of the comment to find comments by the bot
-COMMENT_MARKER = ""
-
-# Fetch existing AI explanation comment
-existing_explanation_comments = []
-comments = pr.get_issue_comments()
-for comment in comments:
- if comment.user.login == "github-actions[bot]" and COMMENT_MARKER in comment.body:
- existing_explanation_comments.append(comment)
-
-# OpenAI prompt template
-prompt_template = """
-You are an expert software engineer reviewing a pull request (PR) that introduces enhancements or
-bugfixes to a software project. Your task is to assess the changes made in the PR and provide a
-detailed summary, test suggestions, code quality assessment, and security assessment.
-
-To produce an assessment that can be processed with a script, you generate a JSON object that
-describes a PR diff. Your response should be a JSON object with the following keys:
-
-- title (string)
-- summary (markdown string that starts with the title "# PR Summary")
-- test_suggestions (array of strings)
-- code_quality_assessment (array of strings)
-- security_assessment (array of strings)
-
-## Instructions for Computing the value of each field
-
-- The `title` field should be a concise summary of the changes.
-- The `summary` field should provide a detailed markdown description of the PR, titled "# PR Summary".
- - The `summary` should focus on the functional changes introduced by the PR.
- - The `summary` should omit mentioning version updates from files like `pyproject.toml` or `package.json`, formatting changes, or other trivial modifications.
-- The `test_suggestions` field should list test suggestions as an array of strings.
-- The `code_quality_assessment` field should provide an assessment of the code quality as an array of strings. It can be "None" if there are no specific concerns.
-- The `security_assessment` field should provide an assessment of the security implications as an array of strings. It can be "None" if there are no specific concerns.
-
-diff:
-```
-{diff}
-```
-"""
-
-# Prepare OpenAI prompt
-prompt = prompt_template.format(diff=diff)
-
-try:
- # Call OpenAI API
- client = OpenAI()
- response = client.chat.completions.create(
- model="o3-mini",
- response_format={"type": "json_object"},
- messages=[
- {
- "role": "user",
- "content": prompt,
- }
- ],
- )
-except APIConnectionError as e:
- print(f"OpenAI API connection error: {e}")
- sys.exit(0) # happy exit so that the workflow will continue
-except OpenAIError as e:
- print(f"OpenAI API error: {e}")
- sys.exit(0) # happy exit so that the workflow will continue
-except Exception as e:
- print(f"Unexpected error: {e}")
- sys.exit(0) # happy exit so that the workflow will continue
-
-# Parse OpenAI response
-ai_response = json.loads(response.choices[0].message.content.strip())
-
-# Create a new comment and delete the existing explanation comment
-new_comment = pr.create_issue_comment(
- f"{COMMENT_MARKER}\n"
- f"{ai_response['summary']}\n\n"
- f"## Test Suggestions\n"
- f"- " + "\n- ".join(ai_response["test_suggestions"])
- if ai_response.get("test_suggestions", None)
- else (
- "n/a" + "\n\n## Code Quality Assessment\n- " + "\n- ".join(ai_response["code_quality_assessment"])
- if ai_response.get("code_quality_assessment", None)
- else (
- "n/a" + "\n\n## Security Assessment\n- " + "\n- ".join(ai_response["security_assessment"])
- if ai_response.get("security_assessment", None)
- else "n/a" + "\n\n"
- )
- )
-)
-
-# Delete all previous AI explain comments
-for comment in existing_explanation_comments:
- try:
- comment.delete()
- except Exception as e:
- print(f"Failed to delete comment: {e!s}")
diff --git a/.github/workflows/ai_explain.yaml b/.github/workflows/ai_explain.yaml
deleted file mode 100644
index 587ff35acd..0000000000
--- a/.github/workflows/ai_explain.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-name: PR Explanation
-
-permissions:
- contents: write
- pull-requests: write
-
-on:
- pull_request:
- types: [opened, synchronize]
-
-jobs:
- explain-pr:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.11"
-
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install openai
- pip install PyGithub
-
- - name: Explain PR
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- OPENAI_API_KEY: ${{ secrets.OPENAI_PR_SUMMARY_KEY }}
- GITHUB_REPOSITORY: ${{ github.repository }}
- GITHUB_REF: ${{ github.ref }}
- run: python .github/workflows/ai_explain.py
diff --git a/AGENTS.md b/AGENTS.md
index dd7fa67ec4..ea895c86c1 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -49,6 +49,19 @@ Documentation is written in Quarto Markdown (`.qmd`). Key conventions:
- Cross-references use relative paths ending in `.qmd`
- Images are stored alongside their `.qmd` files
+## Documentation coverage reviews
+
+When validating documentation coverage for a Shortcut story or engineering change:
+
+- Read the full story and inspect the final implementation pull requests. Treat the implemented behavior as authoritative when it differs from the story description, while verifying merge and release state before calling it shipped.
+- Compare that behavior with documentation on current `origin/main` and classify coverage as Covered, Partial, Outdated, Missing, or Source Gap.
+- Search for every consumer of edited Quarto includes and validate all affected formats, including both HTML guides and RevealJS training where applicable.
+- Render affected pages one at a time. Use `skills/validmind-docs-coverage/scripts/render-pages.sh` for multi-page validation.
+- Add direct links to each changed page in the pull request after the ready-for-review `validate` job deploys the preview.
+- Verify current review, validation, and merge state immediately before describing a pull request in Shortcut or a release tracker. Do not update tracker task state unless explicitly requested.
+
+For the complete Shortcut-to-documentation workflow, use [ValidMind documentation coverage](skills/validmind-docs-coverage/SKILL.md).
+
## Pull requests and release notes
Documentation pull requests must follow the repository's release-note policy:
diff --git a/site/guide/workflows/_add-new-workflows.qmd b/site/guide/workflows/_add-new-workflows.qmd
index 7d270c88af..0304160abf 100644
--- a/site/guide/workflows/_add-new-workflows.qmd
+++ b/site/guide/workflows/_add-new-workflows.qmd
@@ -47,6 +47,7 @@ iv. Under **Workflow Start**, select when the workflow should be initiated:
- **Manually** — Start this workflow manually.^[[Initiate workflows](/guide/workflows/manage-workflows.qmd#initiate-workflows)]
- **On Artifact Registration** — Start this workflow when an artifact is logged on a record.[^on-artifact-registration]
+- **On Field Change** — Start this workflow when a specific artifact field changes.[^on-artifact-field-change] To configure, select a field under **Artifact Field to Monitor**.
- **Via Webhook** — Start this workflow when a webhook event is received.
v. Under **Workflow Expected Duration**, define the SLA for the workflow based on the start date in days, weeks, months, or years.
@@ -80,6 +81,14 @@ vi. Click **Save Draft** to save your blank workflow, and then [configure your w
When selecting date or date time fields, check **Schedule workflow start for this date** to set the workflow to trigger on the existing date captured in the field rather than when its value changes.
+[^on-artifact-field-change]:
+
+ [Manage artifact fields](/guide/validation/manage-artifact-fields.qmd)
+
+ Only artifact fields available to the selected artifact type appear. Artifact fields that apply to all artifact types also appear. Record fields displayed from the parent record are not available as triggers.
+
+ When selecting date or date time fields, check **Schedule workflow start for this date** to set the workflow to trigger on the existing date captured in the field rather than when its value changes.
+
[^artifact-workflow-record-scopes]:
[Manage inventory record types](/guide/inventory/manage-inventory-record-types.qmd)
@@ -133,9 +142,10 @@ iv. Under **Workflow Start**, select when the workflow should be initiated:
- **Manually** — Start this workflow manually.
- **On Artifact Registration** — Start this workflow when an artifact is logged on a record.
+- **On Field Change** — Start this workflow when a specific artifact field changes. To configure, select a field under **Artifact Field to Monitor**. Only artifact fields available to the selected artifact type appear; record fields displayed from the parent record are not available as triggers.
v. Under **Workflow Expected Duration**, define the SLA for the workflow based on the start date in days, weeks, months, or years.
vi. Click **Save Draft** to save your blank workflow, and then configure your workflow steps.
-::::
\ No newline at end of file
+::::
diff --git a/skills/validmind-docs-coverage/SKILL.md b/skills/validmind-docs-coverage/SKILL.md
new file mode 100644
index 0000000000..61c46e3e05
--- /dev/null
+++ b/skills/validmind-docs-coverage/SKILL.md
@@ -0,0 +1,118 @@
+---
+name: validmind-docs-coverage
+description: Verify and implement documentation coverage for a ValidMind Shortcut story or engineering change by comparing final merged frontend/backend behavior with current documentation, classifying the gap, updating shared Quarto sources, validating every affected guide and training output, and preparing reviewer-ready pull requests and release-tracker updates. Use for single-story docs checks, `needs-docs` tickets, release documentation subtasks, or requests to create a documentation PR for a shipped change.
+---
+
+# ValidMind Documentation Coverage
+
+Validate coverage from implementation evidence, then make the smallest complete documentation change when authorized.
+
+## 1. Establish scope
+
+1. Read the repository `AGENTS.md`.
+2. Fetch the full Shortcut story, including comments, related stories, epic, linked branches, and pull requests.
+3. Identify the final implementation PRs in every affected repository.
+4. Inspect the PR bodies, changed files, relevant patches, tests, merge status, and later corrective PRs.
+
+Treat the final implementation diff as authoritative for behavior when it differs from the Shortcut description. Verify merge and release state separately. Distinguish:
+
+- Customer problem and expected behavior
+- Implemented product behavior
+- Explicit limitations and out-of-scope behavior
+- Proposed architecture that did not ship
+
+Do not treat an `internal` implementation label as evidence that a customer-visible capability needs no documentation.
+
+## 2. Compare with current documentation
+
+1. Fetch the latest `origin/main`.
+2. Extract user-facing terminology, UI labels, routes, configuration, limits, errors, and edge cases from the implementation.
+3. Search documentation with `rg`, starting in the most relevant section under `site/`.
+4. When the change is tied to a product route, consult `chatbot-product-map.md` and its frontend snapshot.
+5. Search for Quarto includes that consume any candidate shared source.
+
+Classify the result:
+
+| Status | Meaning |
+|---|---|
+| Covered | Current docs match the shipped behavior and important limitations. |
+| Partial | The feature is mentioned, but new options or behavior are missing. |
+| Outdated | Current instructions or stated behavior are now wrong. |
+| Missing | No appropriate documentation coverage exists. |
+| Source Gap | Implementation or release state is too uncertain to document safely. |
+
+For a verification-only request, stop after reporting the classification, evidence, affected pages, and recommended scope. Do not edit files or external trackers until authorized.
+
+## 3. Implement an approved update
+
+1. Confirm the worktree and current branch before editing.
+2. Start from current `origin/main` on a `codex/sc--` branch.
+3. Update the smallest authoritative source.
+4. Preserve Quarto variables, `.qmd` cross-references, conditional HTML/RevealJS variants, and existing terminology.
+5. If editing an include, find every consumer:
+
+```bash
+rg -n "_source-name\\.qmd" site --glob '*.qmd'
+```
+
+Document operationally important limitations without exposing unnecessary backend mechanics.
+
+## 4. Validate every consumer
+
+Render every affected parent page and every output format. Quarto accepts one page reliably per invocation for this repository; do not pass multiple page paths to one `quarto render` command.
+
+Use the bundled helper from the repository root:
+
+```bash
+skills/validmind-docs-coverage/scripts/render-pages.sh \
+ guide/example/page.qmd \
+ training/example/module.qmd
+```
+
+Then:
+
+1. Run `git diff --check`.
+2. Inspect rendered HTML under `site/_site/` for the new copy and anchors.
+3. Report render warnings explicitly and determine whether they are introduced by the change.
+4. Do not claim hosted preview success until the GitHub `validate` check passes.
+
+## 5. Prepare the pull request
+
+Follow `.github/pull_request_template.md` and the repository release-note policy.
+
+Include:
+
+- Shortcut story and final implementation PRs
+- Before/after documentation behavior
+- Exact local render commands or helper invocation
+- Special-review assumptions and limitations
+- A user-facing release-note entry
+- The `documentation` label for external content changes
+
+The hosted preview is created only after a draft PR becomes ready for review. Its base path is:
+
+```text
+https://docs-staging.validmind.ai/pr_previews//
+```
+
+After `validate` succeeds:
+
+1. Verify each relevant preview page returns successfully.
+2. Add direct links to every changed rendered page, including useful section or RevealJS slide anchors.
+3. Prefer direct reviewer destinations over the preview root.
+
+## 6. Update release tracking
+
+When asked to update a release documentation tracker:
+
+1. Resolve the exact tracker and subtask for the engineering story.
+2. Comment with the documentation PR link and the behavior covered.
+3. Re-read GitHub state immediately before describing review, validation, or merge status.
+4. Do not mark the tracker task complete unless the user explicitly asks you to do so.
+
+## Evidence rules
+
+- Do not infer deployment or release from a merged PR alone when release evidence is required.
+- Do not describe a PR as approved, validated, or merging without checking current state.
+- If private-repository connectors return `404`, use authenticated `gh` as the fallback and preserve the same evidence standard.
+- Keep `Source Gap` explicit when implementation, configuration, or ownership cannot be verified.
diff --git a/skills/validmind-docs-coverage/agents/openai.yaml b/skills/validmind-docs-coverage/agents/openai.yaml
new file mode 100644
index 0000000000..8e8117054a
--- /dev/null
+++ b/skills/validmind-docs-coverage/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "ValidMind Docs Coverage"
+ short_description: "Verify and publish ValidMind documentation coverage"
+ default_prompt: "Use $validmind-docs-coverage to verify documentation coverage for this Shortcut story and prepare any required docs PR."
diff --git a/skills/validmind-docs-coverage/scripts/render-pages.sh b/skills/validmind-docs-coverage/scripts/render-pages.sh
new file mode 100755
index 0000000000..56aaca1857
--- /dev/null
+++ b/skills/validmind-docs-coverage/scripts/render-pages.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+if [[ "$#" -eq 0 ]]; then
+ echo "Usage: render-pages.sh [...]" >&2
+ exit 2
+fi
+
+repository_root="$(git rev-parse --show-toplevel)"
+site_root="${repository_root}/site"
+
+for requested_page in "$@"; do
+ page="${requested_page#site/}"
+ if [[ ! -f "${site_root}/${page}" ]]; then
+ echo "Page not found: ${requested_page}" >&2
+ exit 2
+ fi
+
+ echo "Rendering ${page}"
+ (
+ cd "${site_root}"
+ quarto render "${page}" --profile development
+ )
+done