Skip to content

Add agent skills for suite setup and test authoring - #13

Merged
techygarg merged 15 commits into
mainfrom
feat/agent-skills
Sep 2, 2026
Merged

Add agent skills for suite setup and test authoring#13
techygarg merged 15 commits into
mainfrom
feat/agent-skills

Conversation

@techygarg

@techygarg techygarg commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds three agent skills — confit-suite-setup, confit-component-tests, confit-integration-tests — plus shared tools/check-testcases.py and tools/verify-suite.sh validators gated by make skills (wired into make ci)
  • Publishes the skills as Claude Code and Codex plugins (repo root doubles as plugin root: .claude-plugin/, .codex-plugin/), documented in doc/ai-skills.md and the changelog
  • Fixes latent defects surfaced while auditing example/ (reversed TestReader args, unused AuthTokenProvider, stale AppLauncher seeding docs, dead appsettings.Tests.json key, no-op UserDbInitializer.Seed) and adds mock.enableLogs (suite.config.yaml) plus example/README.md

Test plan

  • make ci (build + unit + component + skills + integration)
  • make skills validates the tools/scripts against every example suite
  • Install the plugin locally (claude --plugin-dir .) and exercise each skill against example/

The example suites are the reference consumers copy from, so mistakes in them
propagate. Five surfaced while auditing them:

- UserIntegrationTests called TestReader.GetTestsForAFile with its arguments
  reversed. The signature is (testFolderName, fileName); the other two suites
  call it correctly. Harmless today only because the method is unreferenced.
- AuthTokenProvider implemented IAuthTokenProvider but was never referenced. No
  SuiteBootstrapper overload accepts a custom provider — auth is configured
  declaratively — so the class advertised an extension point that is not wired.
- The AppLauncher config described a Startup.SeedDatabase method that does not
  exist. The real mechanism is the IsLocalComponentTests flag selecting an
  in-memory database, with UserDbContext creating the schema once per process.
- appsettings.Tests.json carried an environmentVariables key nothing reads.
  TestSuiteInitializer loads the file as a config source; a nested JSON object is
  never applied as process environment variables.
- UserDbInitializer.Seed had a commented-out body, demonstrating nothing. It now
  seeds reference data, showing where the onStarted hook belongs.

Also aligns the AppLauncher namespace with its folder, and takes the qa
environment URL from ${QA_API_URL} instead of a hardcoded host, matching the
secrets-from-environment rule used everywhere else.
EnableMockServerLogs existed on SuiteConfig but had no config-file equivalent, so
turning it on meant editing fixture code. It is now a mock.enableLogs key,
defaulting to false.

Beyond debugging a stub that will not match, this makes an unknown dependency
surface discoverable. Run a component test with no mock: block and every outbound
call comes back 404 and is logged, with method, path, query and body — enough to
write the interactions from. Because it observes HTTP rather than code, it works
whatever language the service under test is written in, which is the practical way
to build mocks for an AppLauncher suite.

One caveat is documented alongside it: during that loop the test's pass/fail is
meaningless. Unmatched 404s make the service take its dependency-failure path,
which is often the very error the test expected, so a test can pass with every
mock missing. Read the log, not the verdict.
example/ had no README, so a reader arriving from the docs had to infer which of
the three projects demonstrated which startup mode, and which parts of them were
ConfIT and which were the sample User API.

Adds a mode-to-project map, the four things every suite structurally needs, and
two things that look required but are not — TestOutputLogger is optional, proven
by the AppLauncher suite passing null, and appsettings.Tests.json only applies to
in-process mode.

The section that earns its keep is "what is demo-specific": UserDbInitializer,
JustAnotherService, the port numbers, the IsLocalComponentTests flag and the
User.* namespaces, each with the reason it exists. Those are the parts a reader
copies by accident.
Two scripts, both runnable without a build and both exiting non-zero on error, so
either can gate CI. A new `make skills` target runs them against every example
suite and is wired into `make ci`.

check-testcases.py reports what ConfIT would otherwise raise at load time or on
the first failing assertion: a response with no expected body, depends: naming an
unknown or later test, unresolvable {{variables}}, bodyFromFile pointing at a
missing file, mock: blocks in an integration suite, unregistered test files, and
matcher problems — an unknown name, a missing closing parenthesis, or a wildcard
or array index in a semantic path, none of which resolve.

Both read ground truth from src/ConfIT/ rather than hardcoding it: supported
target frameworks come from ConfIT.csproj, and built-in matcher names from
SemanticMatcher.cs, with names registered as custom matchers in the project's own
C# also accepted. A matcher added upstream therefore never leaves the checker
rejecting valid tests.

They live in tools/ beside push_nuget.sh rather than inside a skill, since the two
authoring skills share the first one.
Three skills that teach a coding agent to use ConfIT, split by the job being done
rather than by the feature being used.

confit-suite-setup wires a suite: startup mode, suite.config.yaml, fixture, test
class, auth and filters.

Authoring splits by persona, because these are different jobs even though they
produce nearly the same artifact — the same lifecycle scenario is 89 lines as a
component test and 64 as an integration test, differing only by a mock: block:

- confit-component-tests is the developer mid-implementation. Two inputs: the
  controller, and the mocks behind it. It goes down the call path only as far as
  the outbound calls, which is the one thing a spec can never reveal, and which
  also surfaces the branch points that make error tests writable — a 400 driven by
  changing what a mocked dependency returns, not by changing the request.
- confit-integration-tests is QA post-deployment. Black box, from a spec, a
  Postman collection or a live probe, assuming no access to the service source and
  possibly a different repository. It covers environment selection, auth profiles,
  and the shared-persistent-state problem that makes suites pass once and fail on
  the second run.

No skill carries templates. Each resolves the repository it ships inside and reads
example/ and doc/ directly, so what an agent is shown is what CI verifies. The
resolver walks up from the script's physical location looking for example/, doc/
and skills/ as siblings, which is symlink-safe and works from a plugin cache, a
clone or a local --plugin-dir load. When it cannot resolve, the skill stops rather
than inventing a suite from memory: a confidently stale sample is worse than none.

The skills are honest about what the library cannot do — no cleanup hooks, no
retry for eventual consistency, no request timeouts, no unique-data helpers — and
give the workarounds that do work, such as ${RUN_ID} interpolation for per-run
unique data and a trailing delete test for teardown.
Distribution is plugin-only. Installing a plugin clones the whole repository into
the agent's cache, not just skills/, which is what lets each skill read the live
example/ and doc/ instead of carrying copies that go stale.

.claude-plugin/ makes the repository its own marketplace, so
`/plugin marketplace add techygarg/ConfIT` then `/plugin install confit@confit`
is the whole install. .codex-plugin/ carries the equivalent manifest pointing at
the same skills/ folder.

Onboarding another agent means adding one manifest directory at the repository
root; nothing about the skills changes. skills/ must therefore stay at the root —
both manifests name ./skills/, and the reference resolver expects example/, doc/
and skills/ to be siblings.
Adds doc/ai-skills.md covering the three skills, plugin install for Claude Code
and Codex, and the reasoning behind the shape: why authoring splits by persona,
and why plugins rather than an install script.

The rationale worth keeping: example/ took 21 commits in twelve months, and the
files a template would mirror churned hardest — one .csproj changed 13 times, and
the fixture's shape changed materially when SuiteBootstrapper was introduced. A
stale sample is worse than none, because an agent trusts it over the repository.

Records the maintenance rules in CLAUDE.md: no skill may gain template files, new
patterns go into example/ where CI runs them, and the two authoring skills are not
to be merged back into one.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add agent skills for suite setup and test authoring

✨ Enhancement 📝 Documentation 🧪 Tests 🐞 Bug fix ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Adds persona-specific skills for suite setup, component tests, and integration tests.
• Publishes Claude and Codex plugins with CI-gated suite validation tools.
• Adds configurable mock logging and corrects defects in reference examples.
Diagram

graph TD
  Agents["Coding agents"] --> Manifests["Plugin manifests"] --> Skills["Agent skills"] --> References["Live references"]
  Skills --> Validators["Suite validators"] --> CI["CI pipeline"]
  SuiteConfig["Suite YAML"] --> RuntimeConfig["Mock logging"]
  References --> Validators
  CI --> References
Loading
High-Level Assessment

The repository-backed plugin approach is appropriate because skills can read the same examples and documentation that CI verifies, avoiding stale embedded templates. Standalone templates or an install script were considered but would duplicate fast-changing suite wiring; keeping shared validators in tools/ also avoids diverging copies across skills.

Files changed (40) +3103 / -30

Enhancement (5) +425 / -0
SKILL.mdGuide source-driven component test authoring +128/-0

Guide source-driven component test authoring

• Defines a workflow for confirming component mode, tracing controller dependencies, proposing coverage, authoring mocks and assertions, and validating results.

skills/confit-component-tests/SKILL.md

SKILL.mdGuide black-box integration test authoring +121/-0

Guide black-box integration test authoring

• Defines a contract-first workflow covering environment and auth selection, coverage planning, persistent-state safety, authoring, and repeat-run verification.

skills/confit-integration-tests/SKILL.md

SKILL.mdGuide ConfIT suite setup by startup mode +168/-0

Guide ConfIT suite setup by startup mode

• Defines mode selection, live-reference inspection, project creation, structural wiring, verification, and non-.NET command-mode setup.

skills/confit-suite-setup/SKILL.md

MockConfig.csExpose mock logging in YAML configuration +7/-0

Expose mock logging in YAML configuration

• Adds the EnableLogs property so component suites can configure WireMock request logging declaratively.

src/ConfIT/Config/MockConfig.cs

SuiteConfigurationExtensions.csMap mock logging into runtime configuration +1/-0

Map mock logging into runtime configuration

• Propagates MockConfig.EnableLogs into SuiteConfig.EnableMockServerLogs, defaulting to false when omitted.

src/ConfIT/Extension/SuiteConfigurationExtensions.cs

Bug fix (6) +28 / -23
TestSuiteFixture.csAlign the AppLauncher fixture namespace +1/-1

Align the AppLauncher fixture namespace

• Renames the fixture namespace to match the User.ComponentTests.AppLauncher project directory.

example/User.ComponentTests.AppLauncher/SetUp/TestSuiteFixture.cs

UserComponentTests.csAlign AppLauncher test namespaces +2/-2

Align AppLauncher test namespaces

• Updates the setup import and test namespace to the corrected AppLauncher namespace.

example/User.ComponentTests.AppLauncher/UserComponentTests.cs

suite.config.yamlCorrect AppLauncher startup guidance +8/-4

Correct AppLauncher startup guidance

• Replaces references to nonexistent seeding behavior with the actual environment and database setup, updates the target framework path, and tightens the stop command example.

example/User.ComponentTests.AppLauncher/suite.config.yaml

UserDbInitializer.csImplement idempotent reference-data seeding +16/-12

Implement idempotent reference-data seeding

• Replaces the no-op seed method with guarded insertion of two reference users and clarifies appropriate onStarted seeding scope.

example/User.ComponentTests/SetUp/UserDbInitializer.cs

appsettings.Tests.jsonRemove unused environment-variable configuration +0/-3

Remove unused environment-variable configuration

• Deletes the nested environmentVariables object because loading this JSON file does not apply process environment variables.

example/User.ComponentTests/appsettings.Tests.json

UserIntegrationTests.csCorrect TestReader argument ordering +1/-1

Correct TestReader argument ordering

• Passes the test folder before the filename to GetTestsForAFile, matching its declared signature.

example/User.IntegrationTests/UserIntegrationTests.cs

Tests (1) +71 / -0
SuiteConfigurationTests.csTest mock logging parsing and mapping +71/-0

Test mock logging parsing and mapping

• Covers enabled, omitted, and absent-mock configurations to verify parsing and false-by-default runtime mapping.

test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs

Documentation (17) +1302 / -4
CHANGELOG.mdDocument skills, validators, logging, and example fixes +28/-0

Document skills, validators, logging, and example fixes

• Adds an Unreleased section covering plugin distribution, agent skills, validation tooling, mock logging, reference documentation, and corrected examples.

CHANGELOG.md

CLAUDE.mdRecord agent-skill architecture and maintenance rules +38/-1

Record agent-skill architecture and maintenance rules

• Documents the make skills command, persona-based skill split, repository-backed references, plugin layout, and CI validation requirements.

CLAUDE.md

README.mdAdvertise installable AI agent skills +11/-1

Advertise installable AI agent skills

• Adds Claude installation commands, links the agent-skills guide, and directs readers to the curated example project map.

README.md

Package.Readme.mdLink package users to agent skills +8/-0

Link package users to agent skills

• Explains that agent skills are distributed separately from the NuGet package and links to their repository documentation.

doc/Package.Readme.md

ai-skills.mdDocument agent skill installation and design +178/-0

Document agent skill installation and design

• Introduces the three skills, persona split, plugin architecture, live-reference strategy, bundled validators, directory layout, and maintenance constraints.

doc/ai-skills.md

doc-strategy.mdTrack the AI skills guide +1/-0

Track the AI skills guide

• Adds ai-skills.md to the documentation inventory with its intended coverage.

doc/doc-strategy.md

mock-interactions.mdDocument YAML-driven mock request discovery +23/-1

Document YAML-driven mock request discovery

• Replaces fixture-only logging guidance with mock.enableLogs and describes using unmatched WireMock traffic to discover outbound dependencies.

doc/mock-interactions.md

suite-setup.mdDocument mock.enableLogs in suite configuration +2/-1

Document mock.enableLogs in suite configuration

• Adds the YAML option to the setup example and explains its debugging and dependency-discovery behavior.

doc/suite-setup.md

README.mdCurate the three reference suite modes +93/-0

Curate the three reference suite modes

• Maps startup modes to example projects, identifies required suite structure, separates demo-specific details, and lists execution commands.

example/README.md

suite.config.yamlShow optional WireMock request logging +2/-0

Show optional WireMock request logging

• Adds commented mock.enableLogs guidance for debugging and discovering outbound calls.

example/User.ComponentTests/suite.config.yaml

README.mdIntroduce the ConfIT skills collection +81/-0

Introduce the ConfIT skills collection

• Summarizes the three persona-based skills, plugin installation, invocation examples, live-reference requirement, and standalone validators.

skills/README.md

mock-discovery.mdTeach outbound dependency and stub discovery +172/-0

Teach outbound dependency and stub discovery

• Explains call-path tracing, branch analysis, mock URL wiring, minimal stub matching, traffic observation, and unmatched-request diagnosis.

skills/confit-component-tests/references/mock-discovery.md

writing-tests.mdProvide a component test DSL reference +109/-0

Provide a component test DSL reference

• Documents response-body requirements, DSL fields, matcher selection, test chaining, verified examples, and failure diagnosis for component suites.

skills/confit-component-tests/references/writing-tests.md

environments-and-auth.mdExplain integration environments and authentication +127/-0

Explain integration environments and authentication

• Documents environment precedence, supported auth profiles, suite-level credential constraints, OAuth2 lifecycle caveats, auth coverage, and secret interpolation.

skills/confit-integration-tests/references/environments-and-auth.md

state-and-data.mdDefine persistent test-data practices +138/-0

Define persistent test-data practices

• Describes run-scoped unique data, declarative cleanup, read-only tagging, resilient assertions, and unsupported integration-suite capabilities.

skills/confit-integration-tests/references/state-and-data.md

writing-tests.mdProvide an integration test DSL reference +124/-0

Provide an integration test DSL reference

• Tailors DSL, matcher, chaining, examples, and diagnostics guidance to black-box services and shared environments.

skills/confit-integration-tests/references/writing-tests.md

troubleshooting.mdAdd suite wiring troubleshooting guidance +167/-0

Add suite wiring troubleshooting guidance

• Maps discovery, startup, mocking, authentication, state, environment, and CI symptoms to likely causes and fixes.

skills/confit-suite-setup/references/troubleshooting.md

Other (11) +1277 / -3
marketplace.jsonRegister ConfIT in the generic agent marketplace +20/-0

Register ConfIT in the generic agent marketplace

• Adds local marketplace metadata that exposes ConfIT as an installable testing plugin with installation and authentication policies.

.agent/plugins/marketplace.json

marketplace.jsonPublish the Claude Code marketplace entry +17/-0

Publish the Claude Code marketplace entry

• Defines the repository as a Claude Code marketplace and points its ConfIT plugin entry at the repository root.

.claude-plugin/marketplace.json

plugin.jsonDefine Claude Code plugin metadata +20/-0

Define Claude Code plugin metadata

• Adds versioned plugin identity, ownership, repository, licensing, and testing-related discovery keywords.

.claude-plugin/plugin.json

plugin.jsonDefine the Codex plugin experience +54/-0

Define the Codex plugin experience

• Adds Codex metadata, skill discovery, capabilities, prompts, branding, and marketplace-facing descriptions for the three workflows.

.codex-plugin/plugin.json

MakefileGate agent skills through the CI pipeline +14/-2

Gate agent skills through the CI pipeline

• Adds a skills target that runs both validators against all three example suites and includes it in make ci.

Makefile

suite.config.yamlParameterize the QA API endpoint +1/-1

Parameterize the QA API endpoint

• Replaces the placeholder hardcoded QA hostname with the required QA_API_URL environment variable.

example/User.IntegrationTests/suite.config.yaml

reference-path.shResolve component skill live references +78/-0

Resolve component skill live references

• Adds a symlink-safe repository-root resolver with plugin-root support, integrity checks, diagnostics, and reinstall guidance.

skills/confit-component-tests/scripts/reference-path.sh

reference-path.shResolve integration skill live references +78/-0

Resolve integration skill live references

• Adds a symlink-safe repository-root resolver with plugin-root support, integrity checks, diagnostics, and reinstall guidance.

skills/confit-integration-tests/scripts/reference-path.sh

reference-path.shResolve setup skill live references +78/-0

Resolve setup skill live references

• Adds a symlink-safe repository-root resolver with plugin-root support, integrity checks, diagnostics, and reinstall guidance.

skills/confit-suite-setup/scripts/reference-path.sh

check-testcases.pyAdd static ConfIT test-definition validation +677/-0

Add static ConfIT test-definition validation

• Introduces dependency-free-capable YAML and JSON parsing plus checks for DSL structure, fixtures, variables, dependencies, matchers, suite mode, and project registration.

tools/check-testcases.py

verify-suite.shAdd ConfIT project wiring diagnostics +240/-0

Add ConfIT project wiring diagnostics

• Validates package references, supported frameworks, suite configuration, startup mode, fixture lifecycle, test discovery, filters, and runtime file registration.

tools/verify-suite.sh

@qodo-code-review

qodo-code-review Bot commented Sep 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (3) 📜 Skill insights (0)

Grey Divider


Action required

1. Malformed tests pass validation ✓ Resolved 🐞 Bug ≡ Correctness
Description
The validator ignores an entire YAML/JSON file unless every top-level value already contains an
api mapping, so malformed definitions such as TestA: {} are reported as “no test files” and can
exit successfully. ConfIT itself loads every top-level property and then fails while converting or
executing that malformed test.
Code

tools/check-testcases.py[R339-342]

+    return (
+        isinstance(data, dict)
+        and len(data) > 0
+        and all(isinstance(v, dict) and "api" in v for v in data.values())
Evidence
The checker only adds files satisfying is_test_file, while its no-files path returns success if no
parse errors were recorded. ConfIT's reader instead enumerates every top-level property without this
prefilter and later converts each token to TestCase.

tools/check-testcases.py[338-365]
tools/check-testcases.py[652-655]
src/ConfIT/Reader/TestReader.cs[28-41]
src/ConfIT/Extension/JTokenExtensions.cs[8-11]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`check-testcases.py` silently excludes malformed testcase files when their top-level values do not already resemble valid tests. Those files are still loaded by ConfIT at runtime, allowing the validator and `make skills` to pass a suite that will fail during execution.

## Issue Context
Use the suite's configured/discovered testcase folder or `.csproj` registrations to identify testcase files, then validate every top-level entry and emit an error when a case is not a mapping with an `api` section. The no-test-files condition should also fail when a suite is present.

## Fix Focus Areas
- tools/check-testcases.py[338-366]
- tools/check-testcases.py[652-655]
- src/ConfIT/Reader/TestReader.cs[28-41]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Indented registrations never parse 🐞 Bug ≡ Correctness
Description
verify-suite.sh anchors its XML parsing at column zero, but the example .csproj <None> and
<CopyToOutputDirectory> tags are indented. REGISTERED is therefore empty and make skills
reports every runtime file as unregistered, causing the new CI prerequisite to fail.
Code

tools/verify-suite.sh[R42-46]

+REGISTERED="$(tr '<' '\n' < "$CSPROJ" | awk '
+    /^None[[:space:]]+Update=/      { p = (match($0, /Update="[^"]*"/) ? substr($0, RSTART + 8, RLENGTH - 9) : ""); next }
+    /^CopyToOutputDirectory>/       { if (p != "") { print p; p = "" } next }
+    /^\/None>/                      { p = "" }
+' | tr '\\' '/')"
Evidence
The added parser only matches tags beginning in the first column, whereas the shipped example
project indents all relevant tags. The skills Make target treats the resulting nonzero validator
exit as a failure.

tools/verify-suite.sh[42-56]
example/User.ComponentTests/User.ComponentTests.csproj[30-61]
Makefile[66-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`verify-suite.sh` does not recognize indented `<None Update>` registrations, so its registration check always fails for the repository's example projects and breaks `make skills`.

## Issue Context
The parser splits XML tags onto lines but uses patterns anchored directly at `None`, `CopyToOutputDirectory`, and `/None`. Project files conventionally indent those tags.

## Fix Focus Areas
- tools/verify-suite.sh[42-46]
- example/User.ComponentTests/User.ComponentTests.csproj[30-61]
- Makefile[66-75]

Update the parser to accept leading whitespace, then verify `make skills` succeeds on every listed example suite.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Component auth guidance is wrong ✓ Resolved 🐞 Bug ≡ Correctness
Description
The troubleshooting skill says an auth: block under component: supplies the missing
authorization header, but ForComponent never constructs or attaches the configured auth provider.
Authenticated in-process suites following this guidance continue sending unauthenticated requests,
while only command and integration bootstrappers currently apply declarative auth.
Code

skills/confit-suite-setup/references/troubleshooting.md[R96-99]

+### The `Authorization` header is missing
+
+The `auth:` block must sit inside the section actually in use — `component:`, or the *active*
+integration environment. An `auth:` block under an inactive environment does nothing.
Evidence
ForComponent uses initializer.TestHttpClient, which is constructed without an auth provider. In
contrast, ForCommand and ForIntegration explicitly call ToAuthTokenProvider before creating
their clients.

skills/confit-suite-setup/references/troubleshooting.md[94-106]
src/ConfIT/SuiteBootstrapper.cs[32-53]
src/ConfIT/Runner/Http/TestSuiteInitializer.cs[15-24]
src/ConfIT/SuiteBootstrapper.cs[65-83]
src/ConfIT/SuiteBootstrapper.cs[95-113]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new skill directs users to configure component authentication declaratively, but in-process `ForComponent` ignores `ComponentConfig.Auth` and creates its test client without an auth provider.

## Issue Context
Prefer making component authentication consistent across both component startup modes by creating `cfg.ToAuthTokenProvider()` and attaching it to the in-process `TestHttpClient`. If that cannot be supported, explicitly limit the skill guidance to command mode and document the in-process limitation.

## Fix Focus Areas
- skills/confit-suite-setup/references/troubleshooting.md[94-106]
- src/ConfIT/SuiteBootstrapper.cs[32-53]
- src/ConfIT/Runner/Http/TestSuiteInitializer.cs[15-24]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Missing API URL passes ✓ Resolved 🐞 Bug ≡ Correctness
Description
The suite verifier checks for any indented url: in the entire configuration instead of checking
api.url. A component configuration with only mock.url or a readiness URL is therefore declared
valid even though ConfIT rejects it at load time.
Code

tools/verify-suite.sh[120]

+    grep -Eq '^[[:space:]]+url:' "$CONFIG" || err "no 'api.url' — required in every mode"
Evidence
The shell check is a file-wide grep for any whitespace-prefixed url:. Runtime validation
explicitly requires component.api.url or the active integration environment's api.url.

tools/verify-suite.sh[111-120]
src/ConfIT/Config/SuiteConfiguration.cs[56-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`verify-suite.sh` can satisfy its required API URL check using an unrelated URL elsewhere in the YAML, such as `mock.url`, `auth.tokenUrl`, or `startup.readiness.url`.

## Issue Context
Parse the selected component or integration environment and verify that its `api` mapping contains a nonempty `url`, matching `SuiteConfiguration` validation.

## Fix Focus Areas
- tools/verify-suite.sh[111-120]
- src/ConfIT/Config/SuiteConfiguration.cs[56-82]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Empty readiness passes verification ✓ Resolved 🐞 Bug ≡ Correctness
Description
The command-mode verifier accepts a readiness: block whenever any port: or url: exists
anywhere in the file; the required api.url alone satisfies that grep. Thus an empty readiness
block, or one containing both probe types, passes verification even though ConfIT requires exactly
one readiness target.
Code

tools/verify-suite.sh[R138-142]

+                if grep -q 'readiness:' "$CONFIG"; then
+                    if grep -Eq '^[[:space:]]+(port|url):' "$CONFIG"; then
+                        ok "readiness probe declared"
+                    else
+                        err "readiness: needs exactly one of 'port' or 'url'"
Evidence
The verifier's grep is not scoped beneath readiness and merely tests whether either key appears.
ConfIT's configuration validation calls ExactlyOneSet for the readiness URL and port.

tools/verify-suite.sh[136-146]
src/ConfIT/Config/SuiteConfiguration.cs[66-71]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Command-mode readiness validation uses a global grep, so unrelated URL or port fields satisfy the check and it does not enforce exactly one probe target.

## Issue Context
Inspect only `component.startup.readiness` and require exactly one nonempty `url` or `port`, matching the runtime configuration validator.

## Fix Focus Areas
- tools/verify-suite.sh[136-146]
- src/ConfIT/Config/SuiteConfiguration.cs[66-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Unregistered matchers pass validation ✓ Resolved 🐞 Bug ≡ Correctness
Description
custom_matchers() treats every dictionary-style string key in every project C# file as a
registered semantic matcher, even when the dictionary is unrelated to ConfIT, although ConfIT
recognizes only matchers supplied through SuiteConfig.CustomMatchers. Consequently, a typo or
invalid matcher matching an unrelated dictionary key can pass check-testcases.py validation and
then fail at runtime with an unknown-matcher exception.
Code

tools/check-testcases.py[R397-402]

+            try:
+                text = open(os.path.join(base, name), encoding="utf-8-sig", errors="replace").read()
+            except OSError:
+                continue
+            found.update(re.findall(r'\["([A-Za-z][A-Za-z0-9_]*)"\]\s*=', text))
+    return found
Evidence
The validator recursively scans all C# source, extracts key literals matching its
dictionary-initializer regex, and merges them into the approved matcher set. Runtime validation
instead accepts only built-in matchers or custom names from the customMatchers dictionary
populated from suite configuration and supplied to SuiteBootstrapper, rejecting every other name.

tools/check-testcases.py[389-402]
tools/check-testcases.py[657-664]
src/ConfIT/Matching/SemanticMatcher.cs[24-42]
src/ConfIT/SuiteBootstrapper.cs[118-133]
src/ConfIT/SuiteBootstrapper.cs[120-132]
src/ConfIT/Matching/SemanticMatcher.cs[24-41]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The testcase validator whitelists arbitrary C# dictionary keys as semantic matcher names, including keys from dictionaries unrelated to ConfIT. This can hide invalid test definitions that ConfIT later rejects at runtime because the corresponding dictionary was never assigned to `SuiteConfig.CustomMatchers`.

## Issue Context
Runtime matcher validation permits only built-in matchers or keys in the `customMatchers` argument populated from suite configuration. The checker instead scans all project C# source indiscriminately; restrict detection to dictionaries demonstrably passed through a `SuiteBootstrapper.ForComponent`, `ForCommand`, or `ForIntegration` custom-matchers argument, or avoid whitelisting custom matchers when registration cannot be established reliably.

## Fix Focus Areas
- tools/check-testcases.py[389-402]
- tools/check-testcases.py[657-664]
- src/ConfIT/Matching/SemanticMatcher.cs[24-42]
- src/ConfIT/SuiteBootstrapper.cs[118-133]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
7. Cleanup runs without created ID ✓ Resolved 🐞 Bug ≡ Correctness
Description
The documented trailing cleanup test has no dependency on CreateOrder but interpolates
{{orderId}}; when creation fails, VariableInjector.Inject throws before the DELETE request. This
turns the intended harmless cleanup into an additional failing test that obscures the original
failure.
Code

skills/confit-integration-tests/references/state-and-data.md[R58-63]

+DeleteOrder_Cleanup:
+  tags: [orders, cleanup]
+  api:
+    request:
+      method: DELETE
+      path: "/api/order/{{orderId}}"
Evidence
Tests without dependencies enter RunTest, where variable injection occurs before the HTTP call.
Resolving a missing environment/extracted variable throws, while a declared failed prerequisite
would instead be skipped before that point.

skills/confit-integration-tests/references/state-and-data.md[49-74]
src/ConfIT/BaseTest.cs[81-85]
src/ConfIT/BaseTest.cs[117-151]
src/ConfIT/Variable/VariableInjector.cs[121-136]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The integration skill's cleanup example sends a request containing `{{orderId}}` without depending on the test that extracts it. If the create test fails, the variable is absent and the cleanup itself fails during variable injection.

## Issue Context
A dependency on `CreateOrder` skips cleanup when no resource could have been created, while still allowing cleanup after unrelated middle tests fail. This preserves the recipe's stated goal of trailing cleanup.

## Fix Focus Areas
- skills/confit-integration-tests/references/state-and-data.md[49-74]
- src/ConfIT/BaseTest.cs[81-85]
- src/ConfIT/BaseTest.cs[117-151]
- src/ConfIT/Variable/VariableInjector.cs[121-136]

Add `depends: CreateOrder` to the cleanup example and revise the accompanying caveat to describe the skip behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Component state is not fresh ✓ Resolved 🐞 Bug ≡ Correctness
Description
The component skill unconditionally promises fresh state and says fixed literals are safe, but
ConfIT does not reset databases for either in-process or command-mode component suites. Applications
backed by persistent storage will retain those literals across runs and generated create tests can
fail on subsequent executions.
Code

skills/confit-component-tests/SKILL.md[R85-88]

+- **State is fresh each run**, so exact-value assertions are safe and preferred. Assert the real
+  `name`, `email`, `age`; reach for `semantic`/`ignore` only for genuinely server-generated
+  fields such as an id or a timestamp.
+- **Fixed literal test data is fine here** — the in-memory database resets per process. Do not
Evidence
The in-process bootstrapper only starts the host and invokes an optional caller-provided hook; its
initializer performs configuration and client creation without database reset logic. Command mode
merely launches an external process, so its storage lifecycle is also application-controlled.

skills/confit-component-tests/SKILL.md[83-90]
src/ConfIT/SuiteBootstrapper.cs[32-53]
src/ConfIT/Runner/Http/TestSuiteInitializer.cs[15-24]
src/ConfIT/Runner/Http/TestSuiteInitializer.cs[51-64]
src/ConfIT/SuiteBootstrapper.cs[65-83]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The component-testing skill states that all component suites receive fresh state and may safely use fixed test data. ConfIT only starts the application; database reset and isolation remain application-specific.

## Issue Context
Tell the agent to verify the target application's database setup or explicit reset hook before assuming deterministic state. Recommend run-unique data or cleanup when command mode or persistent stores are used.

## Fix Focus Areas
- skills/confit-component-tests/SKILL.md[83-90]
- src/ConfIT/SuiteBootstrapper.cs[32-53]
- src/ConfIT/SuiteBootstrapper.cs[65-83]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Python uses decorative banners 📘 Rule violation ⚙ Maintainability
Description
check-testcases.py introduces repeated-punctuation comments as visual section dividers. The file
therefore violates the prohibition on decorative comment banners.
Code

tools/check-testcases.py[30]

+# --------------------------------------------------------------------------- YAML subset
Evidence
Rule 897522 treats a file as violating when it contains at least one repeated-punctuation comment
used as a section divider. The added Python file contains seven long hyphen banners whose only
purpose is visual grouping.

Rule 897522: Disallow decorative comment banners; use #region/#endregion for sections
tools/check-testcases.py[30-30]
tools/check-testcases.py[264-264]
tools/check-testcases.py[640-640]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Python validator uses long hyphen-based comment banners as visual section dividers.

## Issue Context
Compliance rule 897522 prohibits decorative comment banners. Remove the repeated punctuation and rely on the file's functions and classes for organization, or replace each banner with a concise prose comment where clarification is necessary.

## Fix Focus Areas
- tools/check-testcases.py[30-30]
- tools/check-testcases.py[264-264]
- tools/check-testcases.py[298-298]
- tools/check-testcases.py[335-335]
- tools/check-testcases.py[369-369]
- tools/check-testcases.py[597-597]
- tools/check-testcases.py[640-640]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Shell uses decorative banners 📘 Rule violation ⚙ Maintainability
Description
verify-suite.sh introduces repeated-punctuation comments as visual section dividers even though
its section() helper already labels those sections. The file therefore violates the prohibition on
decorative comment banners.
Code

tools/verify-suite.sh[65]

+# --------------------------------------------------------------------- project references
Evidence
Rule 897522 prohibits repeated-punctuation section banners. The added shell script uses long hyphen
comments before its section labels, while section() at line 23 already supplies the meaningful
organization.

Rule 897522: Disallow decorative comment banners; use #region/#endregion for sections
tools/verify-suite.sh[20-23]
tools/verify-suite.sh[65-66]
tools/verify-suite.sh[99-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shell validator uses long hyphen-based comments as visual section dividers.

## Issue Context
Compliance rule 897522 prohibits decorative comment banners. The following banners are redundant because each is immediately followed by a call to the existing `section()` helper.

## Fix Focus Areas
- tools/verify-suite.sh[65-65]
- tools/verify-suite.sh[99-99]
- tools/verify-suite.sh[162-162]
- tools/verify-suite.sh[185-185]
- tools/verify-suite.sh[207-207]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Parsing tests lack phase structure 📘 Rule violation ⚙ Maintainability
Description
The new LoadComponent parsing tests are non-trivial but do not separate and label their setup,
action, and assertion phases with Given, When, and Then comments. This violates the required
test structure and reduces test readability.
Code

test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs[R51-53]

+    public void LoadComponent_MockEnableLogsTrue_ParsesFlag()
+    {
+        var path = Write("""
Evidence
Rule 897534 requires non-trivial tests to contain separately labeled Given, When, and Then
sections. Both added parsing tests perform configuration setup, loading/assertion behavior, and
cleanup without the required phase comments, and the first test also has multiple assertions.

Rule 897534: Structure test methods using Given / When / Then with spacing and comments
test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs[51-74]
test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs[78-97]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new non-trivial parsing tests do not clearly separate and label their setup, action, and assertion phases.

## Issue Context
Compliance rule 897534 requires non-trivial tests to use distinct `Given`, `When`, and `Then` blocks with blank-line separation. Preserve the existing `try`/`finally` cleanup behavior while restructuring the test bodies.

## Fix Focus Areas
- test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs[51-98]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 21 rules
Review mode: 🧠 Deep: This broad PR introduces substantial independent logic across validators, shell tooling, plugin manifests, skills, CI wiring, and runtime configuration, creating many plausible subtle defects across separate paths.

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +51 to +53
public void LoadComponent_MockEnableLogsTrue_ParsesFlag()
{
var path = Write("""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Parsing tests lack phase structure 📘 Rule violation ⚙ Maintainability

The new LoadComponent parsing tests are non-trivial but do not separate and label their setup,
action, and assertion phases with Given, When, and Then comments. This violates the required
test structure and reduces test readability.
Agent Prompt
## Issue description
The new non-trivial parsing tests do not clearly separate and label their setup, action, and assertion phases.

## Issue Context
Compliance rule 897534 requires non-trivial tests to use distinct `Given`, `When`, and `Then` blocks with blank-line separation. Preserve the existing `try`/`finally` cleanup behavior while restructuring the test bodies.

## Fix Focus Areas
- test/ConfIT.UnitTest/Config/SuiteConfigurationTests.cs[51-98]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread tools/check-testcases.py
import re
import sys

# --------------------------------------------------------------------------- YAML subset

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Python uses decorative banners 📘 Rule violation ⚙ Maintainability

check-testcases.py introduces repeated-punctuation comments as visual section dividers. The file
therefore violates the prohibition on decorative comment banners.
Agent Prompt
## Issue description
The Python validator uses long hyphen-based comment banners as visual section dividers.

## Issue Context
Compliance rule 897522 prohibits decorative comment banners. Remove the repeated punctuation and rely on the file's functions and classes for organization, or replace each banner with a concise prose comment where clarification is necessary.

## Fix Focus Areas
- tools/check-testcases.py[30-30]
- tools/check-testcases.py[264-264]
- tools/check-testcases.py[298-298]
- tools/check-testcases.py[335-335]
- tools/check-testcases.py[369-369]
- tools/check-testcases.py[597-597]
- tools/check-testcases.py[640-640]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread tools/verify-suite.sh

echo "ConfIT suite check: $(basename "$CSPROJ")"

# --------------------------------------------------------------------- project references

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Shell uses decorative banners 📘 Rule violation ⚙ Maintainability

verify-suite.sh introduces repeated-punctuation comments as visual section dividers even though
its section() helper already labels those sections. The file therefore violates the prohibition on
decorative comment banners.
Agent Prompt
## Issue description
The shell validator uses long hyphen-based comments as visual section dividers.

## Issue Context
Compliance rule 897522 prohibits decorative comment banners. The following banners are redundant because each is immediately followed by a call to the existing `section()` helper.

## Fix Focus Areas
- tools/verify-suite.sh[65-65]
- tools/verify-suite.sh[99-99]
- tools/verify-suite.sh[162-162]
- tools/verify-suite.sh[185-185]
- tools/verify-suite.sh[207-207]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread tools/check-testcases.py
Comment thread tools/verify-suite.sh Outdated
Comment thread skills/confit-suite-setup/references/troubleshooting.md
Comment thread skills/confit-component-tests/SKILL.md Outdated
Comment thread tools/verify-suite.sh
Comment on lines +42 to +46
REGISTERED="$(tr '<' '\n' < "$CSPROJ" | awk '
/^None[[:space:]]+Update=/ { p = (match($0, /Update="[^"]*"/) ? substr($0, RSTART + 8, RLENGTH - 9) : ""); next }
/^CopyToOutputDirectory>/ { if (p != "") { print p; p = "" } next }
/^\/None>/ { p = "" }
' | tr '\\' '/')"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

9. Indented registrations never parse 🐞 Bug ≡ Correctness

verify-suite.sh anchors its XML parsing at column zero, but the example .csproj <None> and
<CopyToOutputDirectory> tags are indented. REGISTERED is therefore empty and make skills
reports every runtime file as unregistered, causing the new CI prerequisite to fail.
Agent Prompt
## Issue description
`verify-suite.sh` does not recognize indented `<None Update>` registrations, so its registration check always fails for the repository's example projects and breaks `make skills`.

## Issue Context
The parser splits XML tags onto lines but uses patterns anchored directly at `None`, `CopyToOutputDirectory`, and `/None`. Project files conventionally indent those tags.

## Fix Focus Areas
- tools/verify-suite.sh[42-46]
- example/User.ComponentTests/User.ComponentTests.csproj[30-61]
- Makefile[66-75]

Update the parser to accept leading whitespace, then verify `make skills` succeeds on every listed example suite.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread tools/check-testcases.py
Comment thread skills/confit-integration-tests/references/state-and-data.md
ForComponent built the in-process TestHttpClient without ever calling
cfg.ToAuthTokenProvider(), unlike ForCommand and ForIntegration. An auth:
block under a component: section with startup.mode: in-process was parsed
and validated but silently never attached to outbound requests.

TestHttpClient and TestSuiteInitializer already accepted an optional
IAuthTokenProvider; this just threads it through the one call site that
was missing it, so declarative auth now behaves the same in every mode.
Two gaps let malformed input pass silently:

- discover() required every top-level value in a file to already look like
  a test (a dict with an 'api' key) before reporting anything on it at all.
  A malformed entry such as 'TestA: {}' made the whole file invisible to
  the checker instead of flagging the entry — the file was treated like an
  unrelated fixture, not a broken test. TestReader loads it regardless and
  fails at runtime. Now: a directory with at least one properly-shaped test
  file is a test directory, and any dict-shaped sibling there that isn't
  correctly shaped gets reported instead of skipped. A suite.config.yaml
  that declares a section but has zero discovered test files is now an
  error too, instead of a silent pass.

- custom_matchers() whitelisted any '["key"] = ' string literal found in
  any .cs file in the project, regardless of what dictionary it belonged
  to. A typo'd or unregistered matcher name could coincidentally match an
  unrelated dictionary key elsewhere in the codebase and pass validation,
  then fail at runtime with an unknown-matcher exception. Detection is now
  scoped to keys inside a 'Dictionary<string, SemanticMatcherFunc>'
  initializer specifically.
Both checks grepped the whole config file instead of the block they were
meant to validate:

- The api.url check accepted any indented 'url:' anywhere in the file, so
  a component config with only mock.url (and no api.url at all) passed —
  SuiteConfiguration requires component.api.url unconditionally.
- The readiness check accepted any indented 'port:' or 'url:' anywhere in
  the file — satisfied by the required api.url alone — instead of
  requiring exactly one of the two inside the readiness: block itself. An
  empty readiness block, or one with both port and url, passed even though
  SuiteConfiguration.ValidateComponent requires exactly one.

Adds yaml_block(), which extracts the lines nested under a given key by
indentation, and points both checks at the block they actually mean to
inspect.
The component-tests skill stated as fact that state is fresh each run and
fixed literal test data is safe, attributing it to "the in-memory database"
resetting per process. That is true of ConfIT's own example, but it is the
application's behavior, not something ConfIT provides — a command-mode
suite (ForCommand/AppLauncher) may point at a real, persistent store, where
the same literal-data habit produces the same collide-on-second-run bug the
integration-tests skill already warns about.

Reframes both bullets as conditional on confirming the app's own DB setup,
and points to the integration skill's run-unique-data approach for when
freshness isn't confirmed.
The documented trailing-cleanup test interpolated {{orderId}} without
depending on the test that extracts it. If the create test fails,
VariableInjector throws on the unresolved variable before the DELETE
request fires, turning the intended harmless cleanup into a second
failing test that obscures the original one — the opposite of what the
surrounding caveat claimed would happen.

Adds depends: CreateOrder, matching the skip-on-failed-prerequisite
behavior BaseTest already provides, and corrects the caveat to describe
that behavior instead of an assumed no-op.
@techygarg
techygarg merged commit 3bde6ed into main Sep 2, 2026
7 of 8 checks passed
@techygarg
techygarg deleted the feat/agent-skills branch September 2, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant