Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
6c62fef
PDX-0: docs(docs): add reusable loop runner template and PDX-501..505…
mrdailey99 Jun 2, 2026
539cf85
PDX-0: docs(docs): point loop docs at tracked workflow refs only
mrdailey99 Jun 2, 2026
e7b9213
Merge pull request #197 from ProvarTesting/feature/loop-runner-docs
mrdailey99 Jun 2, 2026
380ba23
PDX-501: docs(mcp): scope comparisonType enum sets by step type
mrdailey99 Jun 2, 2026
8a946bd
Merge pull request #198 from ProvarTesting/fix/PDX-501-comparisontype…
mrdailey99 Jun 2, 2026
45e72ca
PDX-502: feat(mcp): add context-aware comparisonType enum validator
mrdailey99 Jun 2, 2026
f8e7966
Merge pull request #199 from ProvarTesting/feature/PDX-502-comparison…
mrdailey99 Jun 2, 2026
4bbe879
PDX-504: fix(mcp): quote sf executable and args for win32 spaces
mrdailey99 Jun 2, 2026
e262e3e
Merge pull request #200 from ProvarTesting/fix/PDX-504-sf-spaces-win32
mrdailey99 Jun 2, 2026
b542c7f
PDX-505: feat(mcp): detect missing provar plugin with PROVAR_PLUGIN_N…
mrdailey99 Jun 2, 2026
ce2d236
Merge pull request #202 from ProvarTesting/feature/PDX-505-provar-plu…
mrdailey99 Jun 2, 2026
1835e80
PDX-0: chore(cli): bump version to 1.5.4
mrdailey99 Jun 2, 2026
5ba2081
Merge pull request #203 from ProvarTesting/chore/bump-version-1.5.4
mrdailey99 Jun 2, 2026
f437b7f
Merge branch 'main' into develop
mrdailey99 Jun 2, 2026
c71654d
PDX-0: chore(docs): use portable, non-personal paths in test and loop…
mrdailey99 Jun 2, 2026
d2c18b8
Merge pull request #204 from ProvarTesting/chore/portable-paths
mrdailey99 Jun 2, 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
14 changes: 13 additions & 1 deletion docs/PROVAR_TEST_STEP_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,9 @@ Verifies field values or element state on the current screen. Must always includ
</apiCall>
```

**Valid `comparisonType` values:** `EqualTo` | `NotEqualTo` | `Contains` | `NotContains` | `StartsWith` | `EndsWith` | `None`
**Valid `comparisonType` values (UI Assert):** `EqualTo` | `Contains` | `StartsWith` | `EndsWith` | `Matches` | `None`

`comparisonType` is a single Provar enum (`com.provar.core.model.base.java.ComparisonType`), but **each step type accepts only a subset of it**. A value used outside its step's subset is _load-blocking_: the whole test case fails to load with `IllegalArgumentException: No enum constant …ComparisonType.<value>`. The set above is the **UI Assert** subset (`uiAttributeAssertion`); it is strictly smaller than the AssertValues subset. In particular `NotEqualTo`, `NotContains`, `NotStartsWith`, `NotEndsWith`, and the relational/presence operators are **valid in AssertValues but not in a UI Assert** — to negate a UI comparison, invert the assertion logic instead. The UI dropdown labels map as: Equals → `EqualTo`, Contains → `Contains`, Starts With → `StartsWith`, Ends With → `EndsWith`, Matches → `Matches`; the no-assert/read-only choices (Ignore / Read) map to the single enum value `None`. For the full AssertValues subset see [AssertValues](#assertvalues).

### UiRead

Expand Down Expand Up @@ -1256,6 +1258,16 @@ Variable-to-variable or variable-to-literal comparison. For UI field assertions
</apiCall>
```

**Valid `comparisonType` values (AssertValues):** `EqualTo` | `NotEqualTo` | `GreaterThan` | `GreaterThanOrEqualTo` | `LessThan` | `LessThanOrEqualTo` | `IsPresent` | `IsEmpty` | `Matches` | `NotMatches` | `Contains` | `NotContains` | `StartsWith` | `NotStartsWith` | `EndsWith` | `NotEndsWith`

This is the **AssertValues** subset of `com.provar.core.model.base.java.ComparisonType` (`assertValuesComparison`) — wider than the [UI Assert](#uiassert) subset. The negation and relational operators (`NotEqualTo`, `NotContains`, `NotStartsWith`, `NotEndsWith`, `NotMatches`, `GreaterThan`, `GreaterThanOrEqualTo`, `LessThan`, `LessThanOrEqualTo`, `IsPresent`, `IsEmpty`) are valid here but **not** on a UI Assert step. Using a value outside this subset is load-blocking (`IllegalArgumentException: No enum constant …ComparisonType.<value>`).

**Comparison semantics and field-type notes:**

- **Direction of `Contains`:** the comparison reads as `expectedValue` _contains_ `actualValue` — i.e. `actualValue` is the substring searched for inside `expectedValue`. Order the arguments accordingly.
- **Encrypted fields:** a SOQL read of an encrypted field returns `null`, not the cleartext. Assert with `IsEmpty` (or compare against `null`) rather than the expected plaintext; an `EqualTo` against the real value will always fail.
- **Rich-text / long-textarea fields:** values come back wrapped in HTML block markup (e.g. `<p>…</p>`), so an exact `EqualTo` against the raw text fails. Use `Contains` (with the inner text as `actualValue`) to match the meaningful content.

---

## BDD Steps
Expand Down
24 changes: 24 additions & 0 deletions docs/loops/_example-instance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Loop prompt — <<TITLE>>

Scaffold + how-to: [loop-template.md](loop-template.md). To run: copy the fenced block below,
paste after `/loop` (no interval → self-paced, one ticket build→merge per iteration).

Copy this file to `docs/loops/<slug>.md`, fill it in, and add a row to the template's Registry.

## At a glance

- **Scope:** <<what this batch covers>>
- **Decisions:** <<autonomy · merge style · key per-ticket choices>>
- **Process order:** <<blocker-safe order>>

## Status

| Ticket | Branch / PR | Merge SHA | Jira | Notes |
| ----------- | ----------- | --------- | ---- | ----- |
| <<PDX-NNN>> | — | — | — | — |

## Prompt

```
<<paste the filled-in template from loop-template.md here>>
```
108 changes: 108 additions & 0 deletions docs/loops/loop-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Loop runner — template & registry

The reusable scaffold for driving a batch of PDX tickets from build → test → validate → merge,
one ticket per self-paced `/loop` iteration, on top of this repo's documented dev workflow
(`.claude/commands/git-workflow.md` + `CLAUDE.md`).

- **This file** = the generic template + how-to + the registry of run prompts.
- **One file per loop prompt** lives beside it in `docs/loops/` (see [Registry](#registry)).
Each instance doc is self-contained and ready to paste after `/loop`.

> Internal working docs — NOT customer-facing. PDX ticket IDs are fine in `docs/loops/`
> (unlike `docs/mcp.md`, `docs/mcp-pilot-guide.md`, `README.md`, the university course).

## Authoring a new loop prompt

1. Copy `docs/loops/_example-instance.md` (or any existing instance) to a new file in `docs/loops/`.
Name it for the batch, e.g. `pdx-NNN-MMM.md` or a short descriptive slug.
2. Query the Jira keys first (`searchJiraIssuesUsingJql` on the keys) to read `issuelinks`
and derive a **blocker-safe PROCESS ORDER** before writing the order line.
3. Fill the `<<…>>` slots in the template below, paste the result into the new instance doc,
and record the decisions + status there.
4. Add a row to the [Registry](#registry).
5. To run it: open the instance doc, copy its fenced prompt, paste after `/loop`
(no interval → self-paced; each iteration takes one ticket build→merge).

## Decisions to make before filling the template

| Decision | Options | Where it lands |
| --------------------- | ---------------------------------------------------------------- | --------------------- |
| Autonomy | pause-before-merge / fully-autonomous-to-merge / stop-after-PR | step 9 + EXCEPTIONS |
| Merge style | merge commit (`--merge`) / squash (`--squash`) | step 9 |
| Ordering | respect `Blocks`/`is blocked by` links; front-load High severity | PROCESS ORDER |
| Per-ticket specifics | enum sources, dup decisions, error codes, etc. | TICKET-SPECIFIC RULES |
| Authoritative sources | confirm before editing — never guess at enums/contracts | TICKET-SPECIFIC RULES |

## Template

```
Drive <<TICKET RANGE, e.g. PDX-NNN → PDX-MMM>> to merged, one ticket per iteration,
<<AUTONOMY: e.g. "fully autonomously">>.

AUTHORITATIVE WORKFLOW: follow .claude/commands/git-workflow.md and
CLAUDE.md exactly (worktree-per-branch, yarn install in
the worktree, commit format, the compile/test/smoke/lint gate, PR template,
Copilot handling) — WITH these overrides for this loop:
- <<AUTONOMY OVERRIDE: e.g. "Run unattended: do NOT stop at the workflow's
CONFIRM points. Only the EXCEPTIONS at the bottom may stop the loop.">>
- Merge style: <<MERGE COMMIT `gh pr merge <n> --merge --delete-branch`
OR squash `--squash`>>.
- Jira cloudId: 3c8a4f06-8ecc-4723-876f-b096b816c6ec.

PROCESS ORDER (respects blockers): <<ordered ticket list>>.
- <<state each "X BLOCKS Y — don't start Y until X is merged AND Closed">>
- <<state each "X may be a DUP of Y — don't start X until Y is merged">>

EACH ITERATION:
1. Pick the FIRST ticket in PROCESS ORDER not yet Closed whose blocker is Closed.
If all are Closed (or closed-as-duplicate), STOP THE LOOP — don't reschedule.
Print a final summary: ticket → PR → merge SHA → Jira status.
2. getJiraIssue, re-read description/acceptance criteria. Transition to In
Progress, assign to me.
3. Create branch + worktree off develop; run `yarn install` in the worktree.
4. Implement per acceptance criteria + this repo's CLAUDE.md: unit tests in
test/unit/mcp/<group>Tools.test.ts, docs/mcp.md for any new error code /
changed tool / enum, smoke entry + TOTAL_EXPECTED bump in
scripts/mcp-smoke.cjs when a tool/validator is added, NO internal PDX ticket
IDs in customer-facing docs.
5. Gate before commit (in the worktree) — all four MUST pass, fix and re-run,
never --no-verify:
yarn compile
node_modules/.bin/nyc node_modules/.bin/mocha "test/**/*.test.ts"
node scripts/mcp-smoke.cjs 2>/dev/null
yarn lint
6. Stage explicitly (never git add -A). Commit format:
<TICKET>: <type>(<scope>): <subject ≤72 chars>
<blank>
RCA: <≥40 chars>
Fix: <≥40 chars>
7. Push (pre-push runs build+test). Open PR to develop using the workflow's PR
template, including the Jira link.
8. Wait for CI + Copilot. Poll `gh pr checks <n>` and `gh pr view <n> --comments`.
Failing check OR valid Copilot/security comment → fix in the same worktree,
commit, push, re-poll. Re-poll patiently; CI + Copilot take minutes.
9. <<MERGE GATE per AUTONOMY: e.g. "CI green AND no unresolved blocking Copilot/
security comments → merge with `gh pr merge <n> --merge --delete-branch`.">>
10. Transition Jira to Closed. Remove the worktree (git worktree remove …; prune).
11. End the iteration; self-pace to the next ticket.

TICKET-SPECIFIC RULES:
<<one block per ticket: corrected basis / authoritative sources / exact
acceptance criteria / dup-vs-fix decisions / new error codes>>

EXCEPTIONS — STOP the loop and ask me (do NOT force or guess) if:
- <<any unresolved input (e.g. an authoritative source not yet supplied)>>
- CI or the pre-push/commit-msg hooks fail in a way you can't resolve after 3
genuine fix attempts.
- A Copilot SECURITY comment can't be confidently resolved.
- Acceptance criteria are ambiguous enough that you'd be guessing at behaviour.
- Any merge conflict against develop that isn't a trivial auto-resolve.
In every stop case, leave the branch/PR in place, report where you stopped and
why, and wait for me.
```

## Registry

| Loop prompt | Scope | Status |
| -------------------------------- | ---------------------------------------------------------------------------- | ----------- |
| [pdx-501-505.md](pdx-501-505.md) | MCP dogfooding fixes (comparisonType enum + sf invocation), 2026-05-29 batch | Not started |
137 changes: 137 additions & 0 deletions docs/loops/pdx-501-505.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Loop prompt — PDX-501 → PDX-505 (MCP dogfooding fixes)

Scaffold + how-to: [loop-template.md](loop-template.md). To run: copy the fenced block below,
paste after `/loop` (no interval → self-paced, one ticket build→merge per iteration).

## At a glance

- **Scope:** MCP dogfooding findings from 2026-05-29 (Provar 307) — comparisonType enum
correctness/validation (501, 502) and sf invocation/plugin robustness (503, 504, 505).
- **Decisions:** fully autonomous to merge · merge-commit style (`--merge`) · enum sets
confirmed from authoritative Provar-Automation testcases · PDX-503 investigate-then-auto-decide
vs PDX-504.
- **Process order:** PDX-501 → PDX-502 → PDX-504 → PDX-503 → PDX-505.

## Status

| Ticket | Branch / PR | Merge SHA | Jira | Notes |
| ------- | ----------- | --------- | ----- | -------------------------------------------------------- |
| PDX-501 | — | — | Draft | comparisonType docs/rules — corrected basis (see prompt) |
| PDX-502 | — | — | To Do | context-aware validator; blocked by 501 |
| PDX-504 | — | — | Draft | sf spaces-in-path (High) |
| PDX-503 | — | — | Draft | reproduce; may close as dup of 504 |
| PDX-505 | — | — | To Do | PROVAR_PLUGIN_NOT_FOUND |

## Prompt

```
Drive PDX-501 → PDX-505 to merged, one ticket per iteration, fully autonomously.

AUTHORITATIVE WORKFLOW: follow .claude/commands/git-workflow.md and
CLAUDE.md exactly (worktree-per-branch, yarn install in
the worktree, commit format, the compile/test/smoke/lint gate, PR template,
Copilot handling) — WITH these overrides for this loop:
- Run unattended: do NOT stop at the workflow's CONFIRM points. Only the
EXCEPTIONS at the bottom may stop the loop.
- Merge style: MERGE COMMIT, not squash: `gh pr merge <n> --merge --delete-branch`.
- Jira cloudId: 3c8a4f06-8ecc-4723-876f-b096b816c6ec.

PROCESS ORDER (respects blockers): PDX-501, PDX-502, PDX-504, PDX-503, PDX-505.
- PDX-501 BLOCKS PDX-502 — don't start 502 until 501 is merged AND Closed.
- PDX-503 may be a DUP of PDX-504 — don't start 503 until 504 is merged.

EACH ITERATION:
1. Pick the FIRST ticket in PROCESS ORDER not yet Closed whose blocker is Closed.
If all are Closed (or closed-as-duplicate), STOP THE LOOP — don't reschedule.
Print a final summary: ticket → PR → merge SHA → Jira status.
2. getJiraIssue, re-read description/acceptance criteria. Transition to In
Progress, assign to me.
3. Create branch + worktree off develop; run `yarn install` in the worktree.
4. Implement per acceptance criteria + this repo's CLAUDE.md: unit tests in
test/unit/mcp/<group>Tools.test.ts, docs/mcp.md for any new error code /
changed tool / enum, smoke entry + TOTAL_EXPECTED bump in
scripts/mcp-smoke.cjs when a tool/validator is added, NO internal PDX ticket
IDs in customer-facing docs.
5. Gate before commit (in the worktree) — all four MUST pass, fix and re-run,
never --no-verify:
yarn compile
node_modules/.bin/nyc node_modules/.bin/mocha "test/**/*.test.ts"
node scripts/mcp-smoke.cjs 2>/dev/null
yarn lint
6. Stage explicitly (never git add -A). Commit format:
<TICKET>: <type>(<scope>): <subject ≤72 chars>
<blank>
RCA: <≥40 chars>
Fix: <≥40 chars>
7. Push (pre-push runs build+test). Open PR to develop using the workflow's PR
template, including the Jira link.
8. Wait for CI + Copilot. Poll `gh pr checks <n>` and `gh pr view <n> --comments`.
Failing check OR valid Copilot/security comment → fix in the same worktree,
commit, push, re-poll. Re-poll patiently; CI + Copilot take minutes.
9. CI green AND no unresolved blocking Copilot/security comments → merge with
`gh pr merge <n> --merge --delete-branch`.
10. Transition Jira to Closed. Remove the worktree (git worktree remove …; prune).
11. End the iteration; self-pace to the next ticket.

TICKET-SPECIFIC RULES:

PDX-501 — CORRECTED BASIS. The ticket's "NotEqualTo is invalid, remove it"
premise is a STEP-CONTEXT conflation; do NOT delete enum values. There is ONE
com.provar.core.model.base.java.ComparisonType enum, and each step type is
constrained to a SUBSET. Both subsets are confirmed from Provar-Automation-
authored testcases:
• AssertValues / assertValuesComparison (apiId
com.provar.plugins.bundled.apis.AssertValues) — valid set from
~/git/provar-manager-regression/tests/ComparisonTypes.testcase:
EqualTo, NotEqualTo, GreaterThan, GreaterThanOrEqualTo, LessThan,
LessThanOrEqualTo, IsPresent, IsEmpty, Matches, NotMatches, Contains,
NotContains, StartsWith, NotStartsWith, EndsWith, NotEndsWith (16)
• UiAssert / uiAttributeAssertion — valid set from the comparisonType
attributes in ~/git/provar-manager-regression/tests/SauceDemo Purchase Flow (Demo).testcase:
EqualTo, Contains, StartsWith, EndsWith, Matches, None (6)
(dropdown labels: Equals→EqualTo, Contains, Starts With→StartsWith,
Ends With→EndsWith, Matches; Ignore/Read→None. Verify the Ignore-vs-Read
distinction against the schema before documenting it as one value.)
Fix = make docs/PROVAR_TEST_STEP_REFERENCE.md, the two rule strings in
src/mcp/rules/provar_best_practices_rules.json (ASSERT-COMPARISON-001,
ASSERT-VALUES-COMPARISON-001), and docs/mcp.md SCOPE each set to its step
type and match the authoritative constants exactly. Add the Section-6
schema-aware notes from the ticket (encrypted→null via SOQL; rich-text/
textarea wrapped in <p>…</p>, use Contains; Contains direction =
expectedValue contains actualValue). Post a Jira comment on PDX-501 recording
the corrected basis (two step-scoped subsets; NotEqualTo valid in AssertValues,
invalid in UI Assert — the real root cause of the dogfooding failure).

PDX-502 — reuse the SAME authoritative subsets from 501 (one source of truth;
do not hand-duplicate). Validator emits ERROR tier and is CONTEXT-AWARE:
AssertValues steps validate against the 16-set; UiAssert/uiAttributeAssertion
validate against the 6-set. Tests: every valid AssertValues constant (incl.
NotEqualTo) PASSES on an AssertValues step; every valid UI constant PASSES on a
UI step; NotEqualTo on a UI step fires ERROR; a constant in NEITHER set (e.g.
"NotEqualToo") fires ERROR. Do NOT use NotEqualTo as a context-free negative
case. Add rule entry, smoke entry + TOTAL_EXPECTED bump, new error code in
docs/mcp.md.

PDX-504 — make sf invocation space-safe for BOTH executable and args on win32
(incl. auto-resolved Program Files paths, not gated on user-supplied sf_path).
Unit tests via setSfPlatformForTesting per the acceptance criteria.

PDX-503 — first reproduce in the MCP context, capturing exitCode/stdout/stderr.
If it ONLY repros with spaced sf paths → close as DUPLICATE of PDX-504 (comment
the evidence, transition to Closed/Duplicate, no code, no PR). Otherwise
implement the hardening fix with a unit test. Record the decision + evidence as
a Jira comment either way.

PDX-505 — add a provar-topic probe + PROVAR_PLUGIN_NOT_FOUND error code
mirroring SfNotFoundError with remediation text (sf plugins install
@provartesting/provardx-cli); unit test + docs/mcp.md Error Codes entry.

EXCEPTIONS — STOP the loop and ask me (do NOT force or guess) if:
- CI or the pre-push/commit-msg hooks fail in a way you can't resolve after 3
genuine fix attempts.
- A Copilot SECURITY comment can't be confidently resolved.
- Acceptance criteria are ambiguous enough that you'd be guessing at behaviour.
- Any merge conflict against develop that isn't a trivial auto-resolve.
In every stop case, leave the branch/PR in place, report where you stopped and
why, and wait for me.
```
Loading