Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
53f8ccb
PDX-0: feat(mcp): add user-facing guide prompts, tool-guide resource,…
mrdailey99 May 8, 2026
fcf9d6a
PDX-0: chore(ci): update QualityOrchestrator to floating v1 tag
mrdailey99 May 8, 2026
05e2e60
PDX-0: fix(mcp): address Copilot review comments on PR #153
mrdailey99 May 8, 2026
021c6af
Merge pull request #154 from ProvarTesting/fix/ci-quality-orchestrato…
mrdailey99 May 8, 2026
d3bbd93
Merge branch 'develop' into feature/agent-framework-guides
mrdailey99 May 8, 2026
bf68e54
Bump package json version to 1.5.0-beta.18
mrdailey99 May 8, 2026
d7532c3
Bump version to 1.5.0-beta.18 in server.json
mrdailey99 May 8, 2026
34c85f8
Merge pull request #153 from ProvarTesting/feature/agent-framework-gu…
mrdailey99 May 8, 2026
19000c0
PDX-463: feat(mcp): fetch NitroX component packages from factPackages…
mrdailey99 May 8, 2026
444d7e0
PDX-463: fix(mcp): correct factPackages path layout and fix lint warn…
mrdailey99 May 9, 2026
019bb87
PDX-463: fix(mcp): address PR review comments on fetch-nitrox-packages
mrdailey99 May 9, 2026
b2d0afc
Merge pull request #156 from ProvarTesting/feature/PDX-463-nitrox-com…
mrdailey99 May 9, 2026
cccf37f
PDX-465: feat(mcp): add bin entry to enable zero-install npx MCP serv…
mrdailey99 May 11, 2026
8773682
PDX-464: fetch NitroX schemas from internal source at build time (#157)
mrdailey99 May 11, 2026
8d483bb
PDX-466: feat(mcp): add AJV JSON schema validation to provar_nitrox_v…
mrdailey99 May 12, 2026
c9ef921
PDX-467: chore(docs): bump version to 1.5.0 stable and remove @beta i…
mrdailey99 May 12, 2026
85516e7
PDX-476: fix(mcp): address Copilot review follow-ups from PR #161 (#162)
mrdailey99 May 12, 2026
eef4f56
PDX-476: test(mcp): assert field/applies_to for AJV additionalPropert…
mrdailey99 May 12, 2026
1f0e482
PDX-000: fix(ci): make npm publish idempotent and wait for registry p…
mrdailey99 May 12, 2026
5ba0c4c
PDX-000: fix(ci): fetch release notes from GitHub API for workflow_di…
mrdailey99 May 12, 2026
36ce286
PDX-468: feat(mcp): add PROVAR_MCP_SCHEMA_MODE and PROVAR_MCP_TOOLS s…
mrdailey99 May 13, 2026
2714a8a
PDX-469: fix(mcp): patch parseActiveGroups comma-only edge case; add …
mrdailey99 May 13, 2026
779edf4
PDX-477: docs(mcp): fix compact description claim and add env var doc…
mrdailey99 May 13, 2026
1f68270
PDX-477: chore(release): bump version to 1.5.1
mrdailey99 May 13, 2026
273ba77
Merge pull request #170 from ProvarTesting/feature/pdx-468-469-startu…
mrdailey99 May 14, 2026
a3029a0
PDX-470: feat(mcp): add detail level, diff mode, and completeness sco…
mrdailey99 May 13, 2026
da9391b
PDX-470: fix(mcp): address Copilot review comments on PR #168
mrdailey99 May 13, 2026
7d10bac
PDX-470: fix(mcp): address remaining Thread B correctness bugs
mrdailey99 May 13, 2026
806fc26
PDX-477: docs(mcp): document detail, baseline_run_id, run_id, complet…
mrdailey99 May 13, 2026
70540b2
PDX-474: feat(mcp): add depth guard and token attribution middleware
mrdailey99 May 13, 2026
eb872dd
PDX-474: fix(mcp): clamp negative depth limit and skip token estimati…
mrdailey99 May 13, 2026
50c8cf8
PDX-474: fix(mcp): clamp depth=0 to default (treat <= 0 as invalid)
mrdailey99 May 13, 2026
b26d3a7
Merge pull request #168 from ProvarTesting/feature/pdx-470-471-473-va…
mrdailey99 May 14, 2026
b4a60a5
PDX-472: feat(mcp): add fields param for field masking (Thread C)
mrdailey99 May 13, 2026
8e850ca
PDX-477: docs(mcp): document fields and detail params for PR #167 fie…
mrdailey99 May 13, 2026
02d7fe4
PDX-474: fix(mcp): share single anon bucket so depth guard fires on s…
mrdailey99 May 14, 2026
c327717
Merge pull request #169 from ProvarTesting/feature/pdx-474-475-middle…
mrdailey99 May 14, 2026
1352f0f
Merge pull request #167 from ProvarTesting/feature/pdx-470-472-field-…
mrdailey99 May 14, 2026
f0e1b25
PDX-478: fix(mcp): parse connections.connection[] and resolve env via…
mrdailey99 May 14, 2026
f2a5700
Merge branch 'main' into develop
mrdailey99 May 15, 2026
1daaec7
PDX-481: fix(prompts): rewrite author-test flow to single-call constr…
mrdailey99 May 15, 2026
cfd309d
Merge pull request #171 from ProvarTesting/fix/pdx-478-connection-parser
mrdailey99 May 15, 2026
706cb9f
PDX-481: fix(test): address Copilot review on PR #173 + add trace script
mrdailey99 May 15, 2026
5276f5e
Merge pull request #173 from ProvarTesting/fix/PDX-481-rewrite-author…
mrdailey99 May 15, 2026
ac77154
PDX-482: feat(mcp): harden testcase tool descriptions for single-call…
mrdailey99 May 15, 2026
47c75e2
PDX-482: fix(mcp): address adversarial review findings on PR #174
mrdailey99 May 15, 2026
ed5ddac
PDX-0: chore(scripts): add token-measure-vs-playwright.cjs
mrdailey99 May 15, 2026
f639754
Merge pull request #175 from ProvarTesting/chore/token-measure-script
mrdailey99 May 15, 2026
348af9a
Merge pull request #174 from ProvarTesting/fix/PDX-482-harden-tool-de…
mrdailey99 May 15, 2026
590c3fc
PDX-483: feat(mcp): add STEPS_REQUIRED runtime guard on testcase_gene…
mrdailey99 May 15, 2026
ec2230b
PDX-484: feat(mcp): carry construct-vs-amend contract into tool titles
mrdailey99 May 15, 2026
da43f1b
PDX-483: docs(mcp): scrub PDX-XXX refs and internal dev notes from cu…
mrdailey99 May 15, 2026
f146dbd
PDX-0: docs(mcp): remove internal ticket references from customer docs
mrdailey99 May 15, 2026
a1037d1
Merge pull request #176 from ProvarTesting/feature/PDX-483-steps-requ…
mrdailey99 May 15, 2026
ab3a340
Merge pull request #178 from ProvarTesting/fix/PDX-0-remove-internal-…
mrdailey99 May 15, 2026
9f34bf4
PDX-484: chore(merge): resolve develop into feature/PDX-484-harden-to…
mrdailey99 May 15, 2026
c950e94
PDX-0: chore(scripts): rename ticket-prefixed scripts and add naming-…
mrdailey99 May 15, 2026
82de452
PDX-0: chore(scripts): make script-name lint recursive per Copilot re…
mrdailey99 May 15, 2026
f7a188d
Merge pull request #177 from ProvarTesting/feature/PDX-484-harden-too…
mrdailey99 May 15, 2026
93aafb1
PDX-0: chore(merge): resolve develop into chore/script-naming-cleanup…
mrdailey99 May 15, 2026
f3284f5
Merge pull request #179 from ProvarTesting/chore/script-naming-cleanup
mrdailey99 May 15, 2026
cc25ea8
PDX-473: fix(mcp) — feed all-level violations into stop decision; dec…
mrdailey99 May 15, 2026
d53f2ae
PDX-469: chore(mcp) — harden MCP infra: typo guard, release token, di…
mrdailey99 May 15, 2026
6933f38
Merge pull request #180 from ProvarTesting/fix/PDX-473-471-validation…
mrdailey99 May 15, 2026
7909b74
Merge pull request #181 from ProvarTesting/chore/PDX-473-481-mcp-hard…
mrdailey99 May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions .github/workflows/DeployManual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ jobs:
registry-url: 'https://registry.npmjs.org'
scope: '@provartesting'
- name: Install dependencies and build
env:
# Required by scripts/fetch-nitrox-packages.cjs to pull the latest
# NitroX schemas and component catalog from ProvarTesting/factPackages
# at release time. Without this, prepack falls back to the bundled
# snapshots and ships them as-is. The auto-provided GITHUB_TOKEN has
# read access to factPackages.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npm install -g @salesforce/cli
yarn
Expand Down Expand Up @@ -75,23 +82,27 @@ jobs:
if: success()
env:
RELEASE_BODY: ${{ github.event.release.body }}
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(node -p "require('./package.json').version")
TAG="${{ github.event.inputs.tag || 'latest' }}"

# --- Determine change notes source ---
if [ -n "$RELEASE_BODY" ]; then
# GitHub Release body provided — use it verbatim
# GitHub Release body provided via release event — use it verbatim
NOTES="$RELEASE_BODY"
else
# Auto-extract from git log since the previous tag
# workflow_dispatch: fetch release notes from the GitHub release for this version
NOTES=$(gh api "repos/${{ github.repository }}/releases/tags/v${VERSION}" --jq '.body' 2>/dev/null || echo "")
fi

if [ -z "$NOTES" ]; then
# Final fallback: auto-extract from git log since the previous tag
if [ "${{ github.event_name }}" = "release" ]; then
# Release event: HEAD is the new tag — find the nearest ancestor tag before it
PREV=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || git tag --sort=-version:refname | head -1)
else
# Manual dispatch: find the nearest ancestor tag from HEAD
# (git describe respects branch ancestry; avoids pulling in commits from sibling branches)
PREV=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || true)
# HEAD^ avoids returning the current tag itself when HEAD is exactly at a tag
PREV=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)
fi

RANGE="${PREV:+${PREV}..}HEAD"
Expand Down
13 changes: 13 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,16 @@ The project uses ESLint with `@typescript-eslint` strict rules. Common gotchas:
- `camelcase` — `nitroX` is valid camelCase (capital X starts the next word)

CI runs lint as part of `sf-prepack` — do not skip with `--no-verify` on the final merge commit.

---

## Script naming convention

Files anywhere under `scripts/` (including nested subdirectories) must be named for what they **do**, not for the ticket that prompted them. Ticket-prefixed names (e.g. `pdx-482-validate.cjs`) leak internal Jira plumbing into the file tree, age poorly once the ticket closes, and surface in customer-visible artifacts (CI logs, PR diffs, repo browsing).

- **Allowed:** `authoring-flow-trace.cjs`, `construction-contract-validate.cjs`, `mcp-smoke.cjs`, `fetch-nitrox-packages.cjs`
- **Rejected:** `pdx-482-validate.cjs`, `PDX_481_trace.cjs`, `scripts/tmp/pdx-999.cjs`, anything whose basename matches `^pdx[-_]?\d+` (case-insensitive)

Enforced by `scripts/lint-script-names.cjs`, which walks `scripts/` recursively and runs as a dependency of `yarn lint` (wireit `lint:script-names`). The check fails the lint step if any ticket-prefixed filename appears at any depth.

Ticket IDs and rationale belong in commit messages and PR descriptions, not in filenames or in user-facing docs (`docs/mcp.md`, `docs/mcp-pilot-guide.md`).
24 changes: 18 additions & 6 deletions docs/PROVAR_TOOL_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,27 @@ provar_properties_set { file_path: "<output_path>", key: "connectionName", valu

## "I want to write a new test"

A Provar test case is a tree (scenarios → UI screens → asserts), not a flat list of steps. The agent that calls `provar_testcase_generate` is responsible for constructing the full tree in **one** call. Splitting authoring across many tool calls causes scenario numbering drift, flat asserts, and inconsistent step types — `provar_testcase_step_edit` is for **amending** an existing test case, not for **constructing** one.

Recommended sequence:

```
1. provar_project_inspect { project_path } ← find coverage gaps first
2. provar_testcase_generate { project_path, name, ... }
3. provar_testcase_step_edit { test_case_path, ... } ← repeat per step
4. provar_testcase_validate { file_path } ← must pass before adding to plan
5. provar_testplan_add-instance { project_path, plan_name, test_case_path }
6. provar_testplan_validate { project_path, plan_name }
1. provar_project_inspect { project_path } ← find coverage gaps first
2. provar_qualityhub_examples_retrieve { object_or_scenario } ← ground in corpus examples for the step types you need
3. provar_testcase_generate { test_case_name, steps: [<ALL steps>] } ← single call, full step tree in one payload
4. provar_testcase_validate { file_path } ← must pass before adding to plan
5. provar_testplan_add-instance { project_path, plan_name, test_case_path }
6. provar_testplan_validate { project_path, plan_name }
```

Use `provar_testcase_step_edit` only when:

- Adding a single step to an existing, already-validated test case
- Fixing a step's attributes after a validation finding
- Targeted edits during debugging

Do **not** use `provar_testcase_step_edit` to construct a test case step-by-step from an empty skeleton — the LLM loses scenario context between calls and the resulting structure is unreliable.

---

## "I want to work with Salesforce metadata"
Expand Down
44 changes: 44 additions & 0 deletions docs/mcp-pilot-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,50 @@ NitroX is Provar's Hybrid Model for locators — it maps Salesforce component-ba

---

### Scenario 12: Construct a Multi-Scenario Test Case in a Single Call

**Goal:** Confirm the AI authors a multi-scenario test case by passing the full step tree to `provar_testcase_generate` in **one** call — not by generating an empty skeleton and looping `provar_testcase_step_edit` per step.

**Background:** A previously observed regression traced to authoring guidance that steered LLMs toward a per-step construction pattern. Multi-call construction drops scenario numbers (e.g. Scenario 1 → Scenario 3, no Scenario 2), flattens asserts that should be nested inside `UiWithScreen` clauses, and produces inconsistent assert API IDs across the case. This scenario exists so the regression class is exercised in pilot evaluation and cannot recur silently.

**Defense in depth.** Three layers protect against the multi-call construction pattern:

1. **Prompt and resource guidance** — authoring prompts and the MCP step-reference resource describe single-call construction as the contract.
2. **Tool-description contract** — `provar_testcase_generate` and `provar_testcase_step_edit` descriptions explicitly mark generate as constructor-only and step_edit as amendment-only, so the LLM reads the contract at every call site (including compact schema mode).
3. **Runtime guard** — `provar_testcase_generate` rejects the exact shape that would produce a skeleton-only file: `steps:[]` + `dry_run:false` + `output_path`. The rejection returns `STEPS_REQUIRED` with `details.suggestion` telling the LLM to pass the full step tree in one call. Empty-steps shapes that don't write a file (dry-run preview, no `output_path`) remain allowed.

If a pilot LLM falls into the multi-call pattern despite the description contract, the runtime guard converts the failure into an actionable error rather than a silently broken file on disk.

**Title-level contract:** the chip-level `title` fields for the two tools — `Generate Test Case (full steps in one call)` and `Amend Existing Test Case Step` — carry the construct-vs-amend split at the tool-picker surface. MCP clients that render only the title (Claude Desktop tool-picker chips, Cursor audit pane, inline tool-call references in chat threads) still expose the contract to the agent before any description is read.

**Prompt:**

> "Create a Provar test case `AccountFlow.testcase` that covers three scenarios:
>
> 1. **Create Account** — navigate to the Account home, click New, set Name = `{AccountName}` and Phone = `{AccountPhone}`, click Save
> 2. **Verify Account on List** — navigate back to the Account list view, assert the Name and Phone values
> 3. **Open Account Detail** — open the just-created Account, assert all saved field values
>
> Use UI On Screen wrappers, AssertValues for value assertions, and reference SetValues variables with `{Name}`. Write to `<project-path>/tests/AccountFlow.testcase`."

**What to look for (PASS):**

- Exactly **one** call to `provar_testcase_generate` with a populated `steps[]` array — not a call with `steps: []` followed by N `step_edit` calls
- The generated XML lists three scenarios numbered consecutively (1, 2, 3 — no skipped numbers)
- Each scenario's UI actions and asserts are nested inside the appropriate `UiWithScreen` clause (or its equivalent grouping element) — not flat siblings under `<steps>`
- Assert step types are consistent across the case (e.g. all `AssertValues`, not mixed `AssertValues` + `UiAssert` for the same purpose)
- `provar_testcase_validate` on the result returns `is_valid: true`

**What to look for (FAIL — regression indicator):**

- Two or more calls to `provar_testcase_generate` for the same file
- A call to `provar_testcase_generate` with `steps: []` followed by `provar_testcase_step_edit` calls
- The generated case skips a scenario number, mixes assert API IDs for similar assertions, or emits asserts as flat siblings rather than nested inside the screen wrapper

If any FAIL indicator appears, report it to the Provar team with the prompt and the generated XML attached.

---

## Security Model

### What the server does
Expand Down
Loading