valent-pipeline 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/pipeline/prompts/qa-a.md +1 -0
- package/pipeline/scripts/query-kb.ts +7 -1
- package/pipeline/steps/common/agent-protocol.md +2 -2
- package/pipeline/steps/common/quality-standards.md +14 -0
- package/pipeline/steps/critic/test-review.md +3 -0
- package/pipeline/steps/qa-a/write-spec.md +20 -0
- package/pipeline/steps/retrospective/directives.md +7 -2
package/package.json
CHANGED
package/pipeline/prompts/qa-a.md
CHANGED
|
@@ -73,6 +73,7 @@ Before finalizing, verify:
|
|
|
73
73
|
- No behavior is spec'd at multiple tiers
|
|
74
74
|
- Every error test case has a specific error code and message pattern
|
|
75
75
|
- Every P0 test case has DB state verification
|
|
76
|
+
- Every P0/P1 AC on an interactive surface (`api`, `ui`) has a human-readable acceptance scenario realized as a Live Smoke Test (api) or UI Integration Smoke Test (ui) row for QA-B to execute against live infrastructure — never left to unit tests alone
|
|
76
77
|
- Seed data uses factory patterns, not raw SQL
|
|
77
78
|
- NFR requirements are tagged ([NFR-PERF], [NFR-SEC], [NFR-REL])
|
|
78
79
|
- Visual validation checkpoints cover all 5 page states for each page (if UI story)
|
|
@@ -78,10 +78,16 @@ switch (mode) {
|
|
|
78
78
|
|
|
79
79
|
case 'directives': {
|
|
80
80
|
const agent = flags['agent'];
|
|
81
|
+
// ALL-DEV is a cross-cutting directive that applies to every developer agent. Include it when
|
|
82
|
+
// the queried agent is one of them, so a per-agent query still sees shared dev directives.
|
|
83
|
+
const DEV_AGENTS = ['BEND', 'FEND', 'DATA', 'MCP-DEV', 'LIBDEV', 'DOCGEN', 'IAC', 'MOBILE'];
|
|
81
84
|
let rows;
|
|
82
85
|
if (agent) {
|
|
86
|
+
const includeAllDev = DEV_AGENTS.includes(agent.toUpperCase());
|
|
83
87
|
rows = db.prepare(
|
|
84
|
-
|
|
88
|
+
includeAllDev
|
|
89
|
+
? "SELECT id, target_agent, directive, reason FROM correction_directives WHERE (target_agent = ? OR target_agent = 'ALL-DEV') AND status = 'active'"
|
|
90
|
+
: "SELECT id, directive, reason FROM correction_directives WHERE target_agent = ? AND status = 'active'"
|
|
85
91
|
).all(agent) as { id: string; directive: string; reason: string }[];
|
|
86
92
|
} else {
|
|
87
93
|
rows = db.prepare(
|
|
@@ -42,7 +42,7 @@ When `signal_delivery` is `thread`: Lead steers you with the Design Council ques
|
|
|
42
42
|
When you need information about project conventions, architectural patterns, existing code structure, or known pitfalls: self-serve from the knowledge base before exploring the codebase directly. Curated knowledge and correction directives answer in seconds what codebase exploration takes minutes to discover.
|
|
43
43
|
|
|
44
44
|
**How to self-serve:**
|
|
45
|
-
1. Read correction directives from `{correction_directives}` — filter for `status: active` entries
|
|
45
|
+
1. Read correction directives from `{correction_directives}` — filter for `status: active` entries whose `target_agent` is your agent role (or `ALL-DEV` if you are a developer agent).
|
|
46
46
|
2. Read curated knowledge files in `{curated_files_path}` — scan file names and section headers for entries relevant to your current task.
|
|
47
47
|
3. If `{knowledge_mode}` is `sqlite`: query the database via CLI (see your read-inputs step for commands).
|
|
48
48
|
4. If `{story_output_dir}/knowledge-context.md` exists: read it directly — this is a pre-compiled reference containing all relevant knowledge for the current story.
|
|
@@ -51,7 +51,7 @@ Reserve direct codebase exploration for when curated knowledge does not have the
|
|
|
51
51
|
|
|
52
52
|
## Correction Directives
|
|
53
53
|
|
|
54
|
-
Read active correction directives from `{correction_directives}`. If the file does not exist or is empty, proceed without directives -- this is expected for new pipelines. Apply ALL directives
|
|
54
|
+
Read active correction directives from `{correction_directives}`. If the file does not exist or is empty, proceed without directives -- this is expected for new pipelines. Apply ALL directives whose `target_agent` matches your agent role **OR** is `ALL-DEV` when you are a developer agent (BEND, FEND, DATA, MCP-DEV, LIBDEV, DOCGEN, IAC, MOBILE) — `ALL-DEV` is a cross-cutting directive that applies to every developer agent, not one surface. If a directive conflicts with these instructions, the directive takes precedence. Log each applied directive in your YAML frontmatter under `correctionsApplied`.
|
|
55
55
|
|
|
56
56
|
## YAML Frontmatter
|
|
57
57
|
|
|
@@ -10,8 +10,22 @@ These are non-negotiable. CRITIC and QA-B enforce them. Every developer agent (B
|
|
|
10
10
|
- **<1.5 minutes per test** -- any test exceeding this is a design problem, not a timeout problem.
|
|
11
11
|
- **Self-cleaning via fixture auto-teardown** -- tests must not leave state behind. Use framework teardown hooks, not manual cleanup.
|
|
12
12
|
- **Explicit assertions in test bodies** -- never hide assertions in helpers. Every test body must contain at least one visible `expect`/`assert`.
|
|
13
|
+
- **Falsifiable assertions** -- every assertion must be able to FAIL when the behavior is wrong. No unfalsifiable disjunctive gates like `expect(a === 0 || b === 0 || fallback).toBe(true)` — a disjunction with a catch-all that is almost always true asserts nothing. Assert the real invariant directly (e.g. "exactly one container exists AND `SELECT 1` succeeds AND no corruption log"), not a condition that passes regardless of outcome.
|
|
14
|
+
- **Bind to the real artifact under test** -- resolve the actual artifact dynamically (built image id, running service/container name, the file the build emits) and assert against THAT. Never assert against a hardcoded tag/name or an artifact that merely happens to exist on your machine. The test: would it still pass on a clean/CI checkout with no leftover state? If it passes only because of an ambient/side-channel artifact, it is broken. (Prove the artifact exists — `expect(imageId).toBeTruthy()` — before inspecting it.)
|
|
15
|
+
- **Statistical assertions match the spec** -- when the spec states a percentile or sample count (e.g. NFR-PERF "P95 < 200ms"), assert exactly that over real samples with warm-up where appropriate. A single-shot `elapsed < 200` is not a P95 and is flaky — it does not satisfy the spec.
|
|
13
16
|
- **Parallel-safe** -- no shared mutable state between tests. Must run cleanly with `--workers=4`.
|
|
14
17
|
|
|
18
|
+
## Pre-Handoff Self-Check — MANDATORY before declaring done
|
|
19
|
+
|
|
20
|
+
CRITIC enforces every item below and will reject on any High finding, costing a full rework cycle. Run this checklist against your own tests BEFORE writing your handoff; fix anything that fails first. (Each recurred across real stories — this is the gap that buys a guaranteed rework cycle if skipped.)
|
|
21
|
+
|
|
22
|
+
- [ ] **Every P0 qa-test-spec case has a named, implemented test.** Count the spec's P0 cases; count your `it(...)`/`test(...)` blocks; a P0 case with no implementation is a High finding. Do not treat a spec note (e.g. "idempotency") as covered unless there is a named test for it.
|
|
23
|
+
- [ ] **No `if`/`switch`/ternary in any test body** (same path every run).
|
|
24
|
+
- [ ] **No unfalsifiable assertions** — no disjunctive/catch-all gates; each assert can fail.
|
|
25
|
+
- [ ] **Tests bind to the real artifact** — no hardcoded tag/name; would pass on a clean/CI machine with no leftover state.
|
|
26
|
+
- [ ] **Statistical/perf assertions match the spec's wording** (percentile + samples, not single-shot).
|
|
27
|
+
- [ ] **No assertion weakening, no infra mocking on happy paths, no hard waits, assertions visible in test bodies.**
|
|
28
|
+
|
|
15
29
|
## Live Infrastructure Standards
|
|
16
30
|
|
|
17
31
|
- **Live tests against running infrastructure** -- tests hit real systems. No mocking databases, APIs, pipelines, servers, or external services for happy-path verification.
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
- **No test deletion** -- all qa-test-spec test cases must have corresponding tests. A missing test is a High finding.
|
|
22
22
|
- **No hard waits** -- `sleep()`, `setTimeout()`, `page.waitForTimeout()` in tests is a High finding.
|
|
23
23
|
- **No conditionals** -- `if` statements in test bodies is a High finding.
|
|
24
|
+
- **Falsifiable assertions** -- a disjunctive/catch-all gate that is almost always true (e.g. `expect(a === 0 || b === 0 || transient).toBe(true)`) asserts nothing. A test that cannot fail when the behavior is wrong is a High finding. Require the real invariant.
|
|
25
|
+
- **Artifact binding** -- a test that asserts against a hardcoded tag/name, or only passes because of an ambient/leftover artifact on the dev's machine (would fail on a clean/CI checkout), is a High finding. The artifact under test must be resolved dynamically and proven to exist before inspection.
|
|
26
|
+
- **Statistical assertions match spec** -- when the spec states a percentile/sample count (NFR-PERF "P95 < Nms"), a single-shot threshold instead is a Med finding (the assertion does not match the spec).
|
|
24
27
|
- **Explicit assertions** -- assertions hidden inside helper functions is a Med finding. Every test body must contain visible `expect`/`assert`.
|
|
25
28
|
|
|
26
29
|
## Output
|
|
@@ -31,6 +31,17 @@ Structure per AC:
|
|
|
31
31
|
- **Edge cases** (P0: required, P1: key boundaries, P2: optional, P3: omit)
|
|
32
32
|
- **Concurrency** (P0: required, P1: if applicable, P2-P3: omit)
|
|
33
33
|
|
|
34
|
+
### The Given-When-Then cases are human-readable acceptance scenarios — QA-B executes them
|
|
35
|
+
|
|
36
|
+
Your Given-When-Then cases are not just developer test stubs; they are the **human-readable acceptance contract** for the story, written in plain user/consumer language (what a person does and observes), independent of implementation. They describe behavior the way a real developer or QA would verify it by hand.
|
|
37
|
+
|
|
38
|
+
For **interactive surfaces this is mandatory and first-class** — it is how the pipeline tests like a real-world human developer, not just by trusting unit tests:
|
|
39
|
+
|
|
40
|
+
- **`api` profile →** realize each acceptance scenario as a row in the **Live Smoke Tests** table (see `api.md`): real HTTP method/URL/body → expected status + response, plus a verification request for every mutation. QA-B starts the real server and drives these with real requests.
|
|
41
|
+
- **`ui` profile →** realize each user-facing scenario as a row in the **UI Integration Smoke Tests** table (see `ui.md`): user action → real API call → expected UI state → DB verification, backed by a real-browser E2E test. QA-B runs these against the live UI + API + DB (and PMCP validates the visual checkpoints).
|
|
42
|
+
|
|
43
|
+
These acceptance scenarios are **owned and executed by QA-B against live infrastructure** — they are the real-world, black-box evidence JUDGE relies on, distinct from (and never replaced by) the developer's own unit tests. Every P0/P1 AC on an interactive surface MUST have one. The Step 9b quality bar below governs the *automated test code*; it complements these acceptance scenarios — it does not replace them.
|
|
44
|
+
|
|
34
45
|
## Step 4: Database State Verification
|
|
35
46
|
|
|
36
47
|
Per-risk DB verification:
|
|
@@ -72,6 +83,15 @@ For each NFR-sensitive path: `[NFR-PERF]` response time + load patterns; `[NFR-S
|
|
|
72
83
|
- If `ui` in `{testing_profiles}` → **MANDATORY.** Read `uxa-spec.md`. If `uxa-spec.md` is missing, send `[BLOCKER]` to Lead — do NOT proceed without it. For each page state define: Checkpoint ID (VV-{NNN}), Page/Route, State (Default/Loading/Empty/Error/Success or custom), AC Reference, Area labels in scope, Screenshot filename (`{story_id}_VV-{NNN}_{page}_{state}.png`), Expected visual elements, Setup instructions, Pass criteria. Write to `{story_output_dir}/visual-validation-checklist.md`.
|
|
73
84
|
- If `ui` NOT in `{testing_profiles}` → skip, note "N/A — no UI profile."
|
|
74
85
|
|
|
86
|
+
## Step 9b: Test Quality Bar — make every case implementable AND falsifiable
|
|
87
|
+
|
|
88
|
+
The dev agents implement exactly what you specify, and CRITIC rejects tests that are weak, unfalsifiable, or bound to the wrong artifact. Spec the bar IN so it is built right the first time (each rule below traces to a real rework cycle):
|
|
89
|
+
|
|
90
|
+
- **Every P0 case is a named, must-implement test** — never leave a P0 (or an idempotency/concurrency requirement for stateful resources) as a prose note. If it matters, give it its own case ID and assertion target so the dev agent implements it directly. For stateful resources (volumes, DBs), enumerate an explicit idempotency case (apply twice → assert no-recreate / no re-init / data intact).
|
|
91
|
+
- **Falsifiable assertion target** — state the real invariant and the exact expected value (status code, row/column value, count, error code + message regex). Forbid disjunctive/catch-all expectations: never spec "passes if A or B or fallback." The assertion must be able to fail when the behavior is wrong.
|
|
92
|
+
- **Bind to the real artifact** — when a case inspects a built artifact (image, container, file), specify that the test resolves it dynamically (the compose-built image id, the actual service/container name) and proves it exists before inspecting it — never a hardcoded tag. Note it must pass on a clean/CI machine with no leftover state.
|
|
93
|
+
- **NFR-PERF wording is statistical** — specify the percentile AND sample count + warm-up (e.g. "P95 < 200ms over 20 sequential samples after one warm-up request"), not a single-shot threshold.
|
|
94
|
+
|
|
75
95
|
## Step 10: Write Final Outputs
|
|
76
96
|
|
|
77
97
|
- Write to `{story_output_dir}/qa-test-spec.md` and `{story_output_dir}/visual-validation-checklist.md` (if applicable)
|
|
@@ -12,13 +12,18 @@ If pattern touches an invariant, do NOT write a CD. Instead:
|
|
|
12
12
|
|
|
13
13
|
For patterns NOT conflicting with invariants:
|
|
14
14
|
|
|
15
|
+
**Scope the directive to the failure mode, not the agent that tripped it.** Before setting `target_agent`, ask: *could another agent hit this same pattern?* Many failure modes are cross-cutting — test quality (missing P0 cases, conditionals/unfalsifiable assertions in tests, artifact-binding, hard waits), handoff-format violations, infra-mocking — and apply to **every** developer agent, not just the one that happened to surface it this sprint. For those:
|
|
16
|
+
- Set `target_agent: ALL-DEV` (BEND, FEND, DATA, MCP-DEV, LIBDEV, DOCGEN, IAC, MOBILE) so the lesson generalizes; do NOT pin a cross-cutting test-quality directive to the single agent that tripped it.
|
|
17
|
+
- Prefer reinforcing the shared contract: if the pattern is a standing rule, the durable fix is `.valent-pipeline/steps/common/quality-standards.md` (the dev self-check) or the QA-A spec / CRITIC checklist — note that in the directive's `reason`. A per-agent directive that restates a shared standard is noise.
|
|
18
|
+
- Only use a single `target_agent` when the pattern is genuinely specific to that agent's surface (e.g. an IAC-only compose idiom, a FEND-only component pattern).
|
|
19
|
+
|
|
15
20
|
**ADD** new directives:
|
|
16
21
|
```yaml
|
|
17
22
|
- id: CD-{batch_number}-{seq}
|
|
18
23
|
status: active
|
|
19
|
-
target_agent: {agent}
|
|
24
|
+
target_agent: {agent | ALL-DEV}
|
|
20
25
|
directive: "{what to do differently}"
|
|
21
|
-
reason: "{evidence from batch}"
|
|
26
|
+
reason: "{evidence from batch; if it restates a shared standard, name the file it belongs in}"
|
|
22
27
|
impact_level: low | medium | high
|
|
23
28
|
created_batch: {batch_number}
|
|
24
29
|
last_reinforced_batch: {batch_number}
|