@harness-engineering/cli 1.25.7 → 1.26.1
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/dist/agents/skills/README.md +1 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +33 -5
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +6 -0
- package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/claude-code/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +25 -1
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +22 -6
- package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +2 -1
- package/dist/agents/skills/claude-code/initialize-test-suite-project/SKILL.md +415 -0
- package/dist/agents/skills/claude-code/initialize-test-suite-project/skill.yaml +35 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +33 -5
- package/dist/agents/skills/codex/harness-execution/SKILL.md +6 -0
- package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/codex/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/codex/harness-planning/SKILL.md +25 -1
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +22 -6
- package/dist/agents/skills/codex/initialize-harness-project/skill.yaml +2 -1
- package/dist/agents/skills/codex/initialize-test-suite-project/SKILL.md +415 -0
- package/dist/agents/skills/codex/initialize-test-suite-project/skill.yaml +35 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +33 -5
- package/dist/agents/skills/cursor/harness-execution/SKILL.md +6 -0
- package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/cursor/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +25 -1
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +22 -6
- package/dist/agents/skills/cursor/initialize-harness-project/skill.yaml +2 -1
- package/dist/agents/skills/cursor/initialize-test-suite-project/SKILL.md +415 -0
- package/dist/agents/skills/cursor/initialize-test-suite-project/skill.yaml +35 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +33 -5
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +6 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +277 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/skill.yaml +60 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +25 -1
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +22 -6
- package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +2 -1
- package/dist/agents/skills/gemini-cli/initialize-test-suite-project/SKILL.md +415 -0
- package/dist/agents/skills/gemini-cli/initialize-test-suite-project/skill.yaml +35 -0
- package/dist/agents/skills/package.json +2 -2
- package/dist/agents/skills/tests/initialize-test-suite-project.test.ts +152 -0
- package/dist/{agents-md-QPO3H5HX.js → agents-md-VI3HLR7E.js} +3 -3
- package/dist/{architecture-IJLXRHZA.js → architecture-ZDDKEVID.js} +4 -4
- package/dist/{assess-project-QU6XIVJK.js → assess-project-Y6W7YDUA.js} +1 -1
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-TNY64AOS.js → check-phase-gate-CXR3VM22.js} +4 -4
- package/dist/{chunk-JJQ3TW2E.js → chunk-2BPPS6YQ.js} +804 -93
- package/dist/{chunk-NKQEMWGT.js → chunk-2FPUPRCY.js} +3419 -126
- package/dist/{chunk-MLOGYWLY.js → chunk-3AMQYWGT.js} +2 -2
- package/dist/{chunk-AS5DQT4S.js → chunk-56A6OXVA.js} +9 -9
- package/dist/{chunk-G5SNXUIK.js → chunk-7GY6WNEI.js} +1 -1
- package/dist/{chunk-SZ3Q4XEO.js → chunk-AMRC4FU2.js} +441 -288
- package/dist/{chunk-K533WNZG.js → chunk-B66LRB5M.js} +1 -1
- package/dist/{chunk-YRBNAHH4.js → chunk-BK4DJIIY.js} +4 -4
- package/dist/{chunk-2DF6OZLG.js → chunk-DBIX3X4H.js} +2 -2
- package/dist/{chunk-LXPRO2FH.js → chunk-FUND5WJR.js} +2 -2
- package/dist/{chunk-FRDS4XGD.js → chunk-JV4Y2U5F.js} +1 -1
- package/dist/{chunk-XVJRFP7W.js → chunk-K56DTX7G.js} +6 -6
- package/dist/{chunk-K35D7HF3.js → chunk-N6B6RKQQ.js} +1 -1
- package/dist/{chunk-LTCEV7VF.js → chunk-NY7DTZ6K.js} +3 -3
- package/dist/{chunk-JPZY7ZQX.js → chunk-OLW7BJ5N.js} +1 -1
- package/dist/{chunk-KVJZQ2MV.js → chunk-ORNEK65Y.js} +1 -1
- package/dist/{chunk-D3XL2FLX.js → chunk-PNNFCVW4.js} +5 -5
- package/dist/{chunk-E5Z6NTTQ.js → chunk-Q3ZLVMQM.js} +1 -1
- package/dist/{chunk-PCOU2UXU.js → chunk-RAVD7QLY.js} +8 -8
- package/dist/{chunk-IQO7IINR.js → chunk-TSVYBDDE.js} +1 -1
- package/dist/{chunk-MCDCZMKN.js → chunk-TY2ESLVL.js} +1 -1
- package/dist/{chunk-TQRCODRJ.js → chunk-VKS3F46M.js} +1 -1
- package/dist/{chunk-GVNT2YC7.js → chunk-WZ7UHPT3.js} +9 -9
- package/dist/{chunk-ZIYLIYN4.js → chunk-YC4EYIER.js} +8 -2
- package/dist/{chunk-IT2KORSK.js → chunk-ZN6ROTYP.js} +1 -1
- package/dist/{ci-workflow-FJYRFZYQ.js → ci-workflow-EW37KVPS.js} +3 -3
- package/dist/{create-skill-6QWJHQYS.js → create-skill-4T5CBSJ2.js} +2 -2
- package/dist/{dist-ZV6GO6FA.js → dist-CJDGASPP.js} +2 -2
- package/dist/{dist-HPWNWCT6.js → dist-NCNAXUFD.js} +41 -1
- package/dist/{docs-7DW3DI4Z.js → docs-4XI2FQW2.js} +4 -4
- package/dist/{engine-P7EE2IWO.js → engine-4L4CDTHU.js} +3 -3
- package/dist/{entropy-HCXRTDFU.js → entropy-PBYSIQYS.js} +3 -3
- package/dist/{feedback-Y4FYN3NR.js → feedback-OTIFW5MK.js} +1 -1
- package/dist/{generate-agent-definitions-3EHPIWBO.js → generate-agent-definitions-CZGUXIIN.js} +4 -4
- package/dist/{graph-loader-KXVS3YK3.js → graph-loader-RDXSEBD7.js} +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +27 -27
- package/dist/{loader-SKHF3JVV.js → loader-UZOXCWFC.js} +3 -3
- package/dist/{mcp-MWYIPDQU.js → mcp-GWVVV6LH.js} +16 -15
- package/dist/{performance-ADWH5NJY.js → performance-5UQPP3XX.js} +4 -4
- package/dist/{review-pipeline-TLKE5OQD.js → review-pipeline-65V4EO6O.js} +3 -3
- package/dist/{runtime-7LYAW7GU.js → runtime-PXX7HNB3.js} +3 -3
- package/dist/{scan-BGJ7TLLV.js → scan-WM7XDUF7.js} +1 -1
- package/dist/{security-5XWINYVB.js → security-CAYDRZIZ.js} +1 -1
- package/dist/{validate-BFFHYHY7.js → validate-CWGXR7QM.js} +4 -4
- package/dist/{validate-cross-check-GQX7OVCR.js → validate-cross-check-BKCNLZYG.js} +3 -3
- package/package.json +10 -10
- package/dist/agents/commands/claude-code/harness/harness.md +0 -36
- package/dist/agents/commands/codex/AGENTS.md +0 -39
- package/dist/agents/commands/codex/harness/add-harness-component/SKILL.md +0 -204
- package/dist/agents/commands/codex/harness/add-harness-component/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/cleanup-dead-code/SKILL.md +0 -257
- package/dist/agents/commands/codex/harness/cleanup-dead-code/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/detect-doc-drift/SKILL.md +0 -191
- package/dist/agents/commands/codex/harness/detect-doc-drift/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/enforce-architecture/SKILL.md +0 -289
- package/dist/agents/commands/codex/harness/enforce-architecture/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-architecture-advisor/SKILL.md +0 -442
- package/dist/agents/commands/codex/harness/harness-architecture-advisor/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-autopilot/SKILL.md +0 -929
- package/dist/agents/commands/codex/harness/harness-autopilot/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-brainstorming/SKILL.md +0 -418
- package/dist/agents/commands/codex/harness/harness-brainstorming/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-code-review/SKILL.md +0 -850
- package/dist/agents/commands/codex/harness/harness-code-review/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-codebase-cleanup/SKILL.md +0 -236
- package/dist/agents/commands/codex/harness/harness-codebase-cleanup/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-debugging/SKILL.md +0 -378
- package/dist/agents/commands/codex/harness/harness-debugging/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-dependency-health/SKILL.md +0 -190
- package/dist/agents/commands/codex/harness/harness-dependency-health/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-docs-pipeline/SKILL.md +0 -472
- package/dist/agents/commands/codex/harness/harness-docs-pipeline/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-execution/SKILL.md +0 -522
- package/dist/agents/commands/codex/harness/harness-execution/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-hotspot-detector/SKILL.md +0 -172
- package/dist/agents/commands/codex/harness/harness-hotspot-detector/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-impact-analysis/SKILL.md +0 -195
- package/dist/agents/commands/codex/harness/harness-impact-analysis/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-integrity/SKILL.md +0 -178
- package/dist/agents/commands/codex/harness/harness-integrity/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-onboarding/SKILL.md +0 -299
- package/dist/agents/commands/codex/harness/harness-onboarding/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-perf/SKILL.md +0 -272
- package/dist/agents/commands/codex/harness/harness-perf/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-planning/SKILL.md +0 -592
- package/dist/agents/commands/codex/harness/harness-planning/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-refactoring/SKILL.md +0 -181
- package/dist/agents/commands/codex/harness/harness-refactoring/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-release-readiness/SKILL.md +0 -701
- package/dist/agents/commands/codex/harness/harness-release-readiness/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-roadmap/SKILL.md +0 -607
- package/dist/agents/commands/codex/harness/harness-roadmap/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-security-scan/SKILL.md +0 -147
- package/dist/agents/commands/codex/harness/harness-security-scan/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-skill-authoring/SKILL.md +0 -314
- package/dist/agents/commands/codex/harness/harness-skill-authoring/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-soundness-review/SKILL.md +0 -1280
- package/dist/agents/commands/codex/harness/harness-soundness-review/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-supply-chain-audit/SKILL.md +0 -255
- package/dist/agents/commands/codex/harness/harness-supply-chain-audit/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-tdd/SKILL.md +0 -189
- package/dist/agents/commands/codex/harness/harness-tdd/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-test-advisor/SKILL.md +0 -171
- package/dist/agents/commands/codex/harness/harness-test-advisor/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-verification/SKILL.md +0 -433
- package/dist/agents/commands/codex/harness/harness-verification/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/harness-verify/SKILL.md +0 -170
- package/dist/agents/commands/codex/harness/harness-verify/agents/openai.yaml +0 -3
- package/dist/agents/commands/codex/harness/initialize-harness-project/SKILL.md +0 -244
- package/dist/agents/commands/codex/harness/initialize-harness-project/agents/openai.yaml +0 -3
- package/dist/agents/commands/cursor/harness/add-harness-component.mdc +0 -200
- package/dist/agents/commands/cursor/harness/cleanup-dead-code.mdc +0 -253
- package/dist/agents/commands/cursor/harness/detect-doc-drift.mdc +0 -187
- package/dist/agents/commands/cursor/harness/enforce-architecture.mdc +0 -304
- package/dist/agents/commands/cursor/harness/harness-architecture-advisor.mdc +0 -457
- package/dist/agents/commands/cursor/harness/harness-autopilot.mdc +0 -924
- package/dist/agents/commands/cursor/harness/harness-brainstorming.mdc +0 -414
- package/dist/agents/commands/cursor/harness/harness-code-review.mdc +0 -865
- package/dist/agents/commands/cursor/harness/harness-codebase-cleanup.mdc +0 -232
- package/dist/agents/commands/cursor/harness/harness-debugging.mdc +0 -374
- package/dist/agents/commands/cursor/harness/harness-dependency-health.mdc +0 -187
- package/dist/agents/commands/cursor/harness/harness-docs-pipeline.mdc +0 -468
- package/dist/agents/commands/cursor/harness/harness-execution.mdc +0 -518
- package/dist/agents/commands/cursor/harness/harness-hotspot-detector.mdc +0 -169
- package/dist/agents/commands/cursor/harness/harness-impact-analysis.mdc +0 -192
- package/dist/agents/commands/cursor/harness/harness-integrity.mdc +0 -175
- package/dist/agents/commands/cursor/harness/harness-onboarding.mdc +0 -296
- package/dist/agents/commands/cursor/harness/harness-perf.mdc +0 -268
- package/dist/agents/commands/cursor/harness/harness-planning.mdc +0 -587
- package/dist/agents/commands/cursor/harness/harness-refactoring.mdc +0 -177
- package/dist/agents/commands/cursor/harness/harness-release-readiness.mdc +0 -697
- package/dist/agents/commands/cursor/harness/harness-roadmap.mdc +0 -603
- package/dist/agents/commands/cursor/harness/harness-security-scan.mdc +0 -162
- package/dist/agents/commands/cursor/harness/harness-skill-authoring.mdc +0 -300
- package/dist/agents/commands/cursor/harness/harness-soundness-review.mdc +0 -1275
- package/dist/agents/commands/cursor/harness/harness-supply-chain-audit.mdc +0 -252
- package/dist/agents/commands/cursor/harness/harness-tdd.mdc +0 -185
- package/dist/agents/commands/cursor/harness/harness-test-advisor.mdc +0 -168
- package/dist/agents/commands/cursor/harness/harness-verification.mdc +0 -429
- package/dist/agents/commands/cursor/harness/harness-verify.mdc +0 -167
- package/dist/agents/commands/cursor/harness/initialize-harness-project.mdc +0 -240
- package/dist/agents/commands/gemini-cli/harness/harness.toml +0 -277
- package/dist/{chunk-RRHUCDRD.js → chunk-ZP5E7YET.js} +3 -3
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# Initialize Test Suite Project
|
|
2
|
+
|
|
3
|
+
> Scaffold or migrate a test-suite project — API, E2E/UI, or shared test library. Owns test-suite-specific archetype selection, shared-library vs in-repo scaffolding decision, layer variants, tag taxonomy, reporter stack, and custom report. Cross-cutting concerns (adoption level, personas, AGENTS.md base template, i18n, knowledge graph, roadmap nudge, final commit) delegate to `initialize-harness-project`.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Initializing a new test-suite project (you already know it is a test suite)
|
|
8
|
+
- Migrating an existing test-suite project to the next adoption level
|
|
9
|
+
- When `initialize-harness-project`'s Phase 1 classification step hands off here
|
|
10
|
+
- NOT when the project is a product or service (use `initialize-harness-project`)
|
|
11
|
+
- NOT when adding a single spec, domain, or fixture to an already-configured test suite (use `add-harness-component`)
|
|
12
|
+
|
|
13
|
+
## Composition with `initialize-harness-project`
|
|
14
|
+
|
|
15
|
+
This skill owns only the _test-suite-specific_ pieces. The generic harness flow belongs to the parent skill. Two invocation patterns:
|
|
16
|
+
|
|
17
|
+
1. **Parent dispatches here.** The user runs `initialize-harness-project`; its Phase 1 step 5 classifies the project as a test suite and dispatches to this skill. Run the parent's Phase 2 (scaffolding) first, then this skill's full flow, then return to the parent for Phase 4 wrap-up (knowledge graph, roadmap, commit).
|
|
18
|
+
|
|
19
|
+
2. **Direct invocation.** The user knows up front it's a test suite and invokes this skill directly. Run the parent's Phase 1 (assess state), Phase 2 (`harness init`), and Phase 3 steps 1–2 and 5 (personas, AGENTS.md base, i18n) inline or by invoking the parent explicitly, then apply this skill's Phase 1–4, then hand back to the parent's Phase 4 steps 4–5.
|
|
20
|
+
|
|
21
|
+
Either way, what this skill owns: archetype selection, shared-library vs scaffold decision, layer-model variants A/B, ESLint flat-config fix, test-framework delegation, env and secrets, auth abstraction, schema validation, fixtures isolation, mocking support, tag-driven organization, reporters, the custom report, CI integration, and "prove the guards fire" verification.
|
|
22
|
+
|
|
23
|
+
## Process
|
|
24
|
+
|
|
25
|
+
### Phase 1: CLASSIFY — Pick the Archetype
|
|
26
|
+
|
|
27
|
+
Before scaffolding, classify the project and record in the assessment.
|
|
28
|
+
|
|
29
|
+
**Test-suite signals** (at least one must apply — re-check even if dispatched from the parent):
|
|
30
|
+
|
|
31
|
+
- Repo or package name matches `*test*`, `*-e2e*`, `*-qa*`, `*-automation*`
|
|
32
|
+
- `package.json` has `@playwright/test`, `cypress`, `webdriverio`, `mocha`, or `testcafe` as a direct dep (frameworks that are _only_ test-related — presence of `vitest`/`jest` alone is not enough)
|
|
33
|
+
- Top-level `tests/`, `e2e/`, `specs/`, or `playwright/` directories are the primary source tree, not an adjunct to `src/`
|
|
34
|
+
- Config files like `playwright.config.*`, `cypress.config.*`, `wdio.conf.*`
|
|
35
|
+
- No production runtime — build output is consumed only by other test repos (shared library)
|
|
36
|
+
|
|
37
|
+
**Archetypes:**
|
|
38
|
+
|
|
39
|
+
- **API test suite** — exercises HTTP APIs end-to-end (e.g. Playwright API tests)
|
|
40
|
+
- **E2E / UI suite** — browser-driven tests (Playwright, Cypress, WebdriverIO)
|
|
41
|
+
- **Shared test library** — API clients, Page Object Models, fixtures, or test users consumed by the above; no tests in-repo
|
|
42
|
+
|
|
43
|
+
### Phase 2: DECIDE — Shared Library or Scaffold In-Repo?
|
|
44
|
+
|
|
45
|
+
For **API** and **E2E/UI** suites, check whether a shared library already exists — typically a team-specific `@<org>/<team>-testing-api-library` for API clients, or an equivalent for Page Object Models. If one exists, consuming it is strongly preferred: one client implementation shared by all test suites is the contract source of truth and avoids drift. Only scaffold an in-repo `src/api/` or `src/page-objects/` tree if no shared library exists or the suite has a genuinely different contract.
|
|
46
|
+
|
|
47
|
+
For **Shared test library** archetypes, this phase is trivial — you _are_ the shared library; scaffold in-repo.
|
|
48
|
+
|
|
49
|
+
Record the decision in AGENTS.md. It determines which layer-model variant applies in Phase 3 step 2.
|
|
50
|
+
|
|
51
|
+
### Phase 3: CONFIGURE — Test-Suite Shape
|
|
52
|
+
|
|
53
|
+
Apply these steps before running validation. Record decisions in AGENTS.md as you go.
|
|
54
|
+
|
|
55
|
+
1. **Pick a domain layout.** Independent of whether clients are in-repo or imported, domains drive the folder layout:
|
|
56
|
+
- **Self-contained suite:** one folder per API domain, feature area, or user flow under `src/api/` or `src/page-objects/`, each exposing a manager/client class (API suites) or Page Object Model (UI suites) that takes an HTTP client or browser context in its constructor. A single composition module wires everything together.
|
|
57
|
+
- **Shared-library consumer:** no per-domain folders in `src/`. Instead, a thin `config/` adapter wraps the shared library's entry point (e.g. exposes `{api, user}` on the Playwright test fixture). Tests are still organized by domain — see step 10 — but the domain folders live under `tests/<domain>/`, not `src/api/<domain>/`.
|
|
58
|
+
|
|
59
|
+
Document the chosen layout in AGENTS.md with a directory tree.
|
|
60
|
+
|
|
61
|
+
2. **Define the layer model.** Two variants — pick the one matching Phase 2.
|
|
62
|
+
|
|
63
|
+
**Variant A — self-contained test suite.** Record in `harness.config.json`:
|
|
64
|
+
- `utils` → helpers, date/string/id utilities (no internal deps)
|
|
65
|
+
- `composition` → single wiring module (e.g. `managers.ts`) → allowed to import every layer below
|
|
66
|
+
- `common` → shared DTOs, enums, error types → `utils`
|
|
67
|
+
- `config` → HTTP client, auth service, environment loader → `utils`, `common`
|
|
68
|
+
- `api` / `domains` / `page-objects` → per-domain managers or POMs → `utils`, `common`, `config`
|
|
69
|
+
- `fixtures` → deterministic seed data, factories, builders → `utils`, `common`, `config`
|
|
70
|
+
- `specs` → top layer; imports composition + fixtures; nothing imports specs
|
|
71
|
+
|
|
72
|
+
Forbid (same-layer rules, enforced via `forbiddenImports`):
|
|
73
|
+
- A domain/POM importing a sibling domain/POM (domains are peers, not hierarchical)
|
|
74
|
+
- `fixtures` importing specs
|
|
75
|
+
- Specs importing each other (tests must be independently runnable in any order)
|
|
76
|
+
|
|
77
|
+
**Variant B — shared-library consumer.** No `common`, no `api` layer — those live in the shared library. Record in `harness.config.json`:
|
|
78
|
+
- `utils` → helpers with no internal deps
|
|
79
|
+
- `config` → thin adapter wrapping the shared library (e.g. builds the `Managers` from the shared lib + current env), token handler, constants → `utils`
|
|
80
|
+
- `fixtures` → Playwright test fixtures that expose `{api, user, ...}` to specs → `utils`, `config`
|
|
81
|
+
- `specs` → top layer; imports `fixtures` → `utils`, `config`, `fixtures`
|
|
82
|
+
|
|
83
|
+
Forbid:
|
|
84
|
+
- Specs bypassing `fixtures` and instantiating the shared library directly — always go through the fixture so auth, base URL, and teardown are consistent
|
|
85
|
+
- `fixtures` importing specs
|
|
86
|
+
- Any layer importing the shared library from outside `config` (forces single adapter point, keeps upgrades localized)
|
|
87
|
+
|
|
88
|
+
**Layer-ordering gotcha — `harness check-deps` and `@harness-engineering/eslint-plugin` both use first-match-wins layer resolution.** Put more-specific patterns _before_ more-general ones in the `layers` array. For Variant A, `composition` (pattern `src/config/managers.ts`) must come before `config` (pattern `src/config/**`), otherwise `managers.ts` is classified as `config` and every `api` import becomes a layer violation. Do not rely on per-layer `excludePatterns` — the CLI and the ESLint plugin both drop that field.
|
|
89
|
+
|
|
90
|
+
**`forbiddenImports` gotcha — no `exceptPaths` support.** The ESLint plugin schema for `forbiddenImports` only accepts `from`, `disallow`, `message` — any other keys (including `exceptPaths`) are silently stripped. Do not write `from: src/config/**, disallow: [src/api/**], exceptPaths: [src/config/managers.ts]` and expect it to work. Use layer ordering (above) to carve out the composition file; reserve `forbiddenImports` for same-layer rules like sibling-domain isolation that the layer graph cannot express.
|
|
91
|
+
|
|
92
|
+
3. **Wire up the ESLint flat config so the forbidden-imports rule actually runs.** `harness init` scaffolds `eslint.config.mjs` that spreads `harnessPlugin.configs.recommended` but does not declare a `files:` glob or a TypeScript parser. Under ESLint 9 flat config this means every `.ts` file is ignored and the rule never fires. Replace the scaffolded config with an explicit block: `files: ['src/**/*.ts', 'tests/**/*.ts']`, `languageOptions: { parser: tsParser, parserOptions: { ecmaVersion: 'latest', sourceType: 'module' } }`, `plugins: { '@harness-engineering': harnessPlugin }`, and the three `'error'` rules (`no-layer-violation`, `no-forbidden-imports`, `no-circular-deps`). Add `@typescript-eslint/parser` to devDependencies. Verify by running `npx eslint 'src/**/*.ts'` and seeing it actually report errors on a deliberately bad file.
|
|
93
|
+
|
|
94
|
+
4. **Pick the test framework(s) and delegate detailed setup to the right skill.** Do not configure the framework here — just record the choice in AGENTS.md and point the human at the follow-up skill:
|
|
95
|
+
- Playwright (API or E2E) → `test-playwright-setup` then `test-playwright-patterns`
|
|
96
|
+
- Vitest → `test-vitest-config`
|
|
97
|
+
- Contract tests → `api-contract-testing` and `test-contract-testing`
|
|
98
|
+
- Mocking (MSW, route interception) → `test-msw-pattern`, `test-mock-patterns`
|
|
99
|
+
- Fixtures / factories → `test-factory-patterns`, `harness-test-data`
|
|
100
|
+
- For shared libraries that are _consumed_ by tests but contain none themselves, skip framework setup entirely — record this in AGENTS.md under "Gotchas" so agents do not try to add Vitest later.
|
|
101
|
+
|
|
102
|
+
5. **Environment and secret handling.** Require a committed `.env.example` listing every variable the suite reads (API base URLs, OAuth client IDs, registry tokens, feature flags). Actual `.env*` files must be gitignored. For multi-environment suites, encode environments as `.env.dev`, `.env.stage`, `.env.prod` and document in AGENTS.md how the runner selects one (env var, CLI flag, or config). Never commit real credentials even as examples — use placeholders like `REPLACE_ME`.
|
|
103
|
+
|
|
104
|
+
6. **Authentication abstraction.** Record in AGENTS.md: token source (OAuth client-credentials, CIAM, basic auth, session cookie), caching strategy (in-memory, file, Redis), and how test users or parent/child scopes are resolved. If a shared test-user library exists (typically `@<org>/<team>-testing-user-library` or similar), link it and forbid inlining user credentials in specs.
|
|
105
|
+
|
|
106
|
+
7. **Schema / contract validation.** Decide whether request and response DTOs are validated at runtime (zod, ajv, io-ts) or only compile-time. Intermediate and above should validate at runtime for contract-drift detection. If adopting zod, reference `zod-schema-definition`.
|
|
107
|
+
|
|
108
|
+
8. **Fixtures and test-data isolation.** Document the per-test isolation strategy in AGENTS.md: unique IDs per run (UUID suffixes, timestamps), teardown hooks, no shared mutable state between specs. Forbid hard-coded production record IDs in fixtures.
|
|
109
|
+
|
|
110
|
+
9. **Mocking support (shared libraries and API clients).** If the project will be consumed by FE or UI test suites that need to mock upstream responses, expose mock response builders (e.g. `buildMockResponse`, `buildMockErrorResponse`) and document the override API in AGENTS.md so consumer projects know the contract.
|
|
111
|
+
|
|
112
|
+
10. **Test organization: tags over folders.** Do _not_ split specs into `tests/smoke/`, `tests/regression/`, etc. Organize specs by domain / feature area (`tests/<domain>/<feature>.spec.ts`) and filter run shape with tags. This matches how Playwright (and most modern runners) expect grep-based filtering to work, and avoids moving a spec file whenever its coverage tier changes.
|
|
113
|
+
|
|
114
|
+
Record the tag taxonomy in AGENTS.md. Baseline for a Playwright API suite:
|
|
115
|
+
- `@smoke` — fast subset; PR gate. Applied per-test or per-describe.
|
|
116
|
+
- Untagged = regression. "Full suite" is just `playwright test` with no grep.
|
|
117
|
+
- **Quarantine tags (never run):** `@known-failure`, `@wip`, `@blocked`, `@archived`. Exclude these globally via `grepInvert` in `playwright.config.ts`:
|
|
118
|
+
```ts
|
|
119
|
+
grepInvert: [/@known-failure/, /@wip/, /@blocked/, /@archived/],
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Filter commands (bake into `package.json` scripts, not ad-hoc CI yaml):
|
|
123
|
+
- `npm run smoke` → `playwright test --grep @smoke`
|
|
124
|
+
- `npm run exhaustive` → `playwright test` (full regression, quarantine excluded)
|
|
125
|
+
- `npm run list` → `playwright test --list` (sanity check after tag edits)
|
|
126
|
+
|
|
127
|
+
**Reporters.** Configure `playwright.config.ts` with the stack that feeds both human and machine consumers:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
reporter: [
|
|
131
|
+
['html', {outputFolder: './test-results/html-test-results', open: 'never'}],
|
|
132
|
+
['list'],
|
|
133
|
+
['github'],
|
|
134
|
+
['json', {outputFile: 'test-results/json-results/results.json'}],
|
|
135
|
+
],
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The `json` reporter is the input to the custom report in step 11. The `github` reporter produces annotations on PRs; `list` is for local stdout; `html` is for deep-dive failure triage.
|
|
139
|
+
|
|
140
|
+
11. **Custom report (enriched HTML + Slack + history).** Playwright's stock HTML report is fine for a single run but does not track trends, categorize failures, or know which tests are quarantined. Scaffold a `scripts/generate-reports.ts` that reads the JSON reporter output (`test-results/json-results/results.json`) and emits an enriched report. Modeled on reference implementations running in production test suites, it should produce:
|
|
141
|
+
- **Failure categorization:** bucket each failure into one of `schema | auth | server | client | timeout | network | other` based on the error message. Surfaces whether a red run is an API regression (schema) vs. infrastructure (timeout/network) vs. test-data problem (auth).
|
|
142
|
+
- **Per-area health:** group by domain folder (first path segment under `tests/`), report pass rate and failing titles per area. Tells you which surface of the product is drifting.
|
|
143
|
+
- **Delta vs history:** append each run to a JSONL ledger keyed by commit. Report new failures since last run and failures since last green — not just "X failed" but "X started failing at commit Y."
|
|
144
|
+
- **Quarantine ledger:** scan for `@known-failure`-tagged tests, track age since first seen in a JSON ledger, flag tests quarantined longer than 14 days.
|
|
145
|
+
- **Slack summary:** short markdown block with pass rate, new failures, and a link to the HTML report. Optional but cheap once the categorization exists.
|
|
146
|
+
- **Environment + git context:** node version, base URL, commit SHA, branch, commit message — so a report opened later tells you where and when it ran.
|
|
147
|
+
|
|
148
|
+
Wire the script into `package.json`:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"scripts": {
|
|
153
|
+
"generate-custom-reports": "npx ts-node scripts/generate-reports.ts",
|
|
154
|
+
"show-custom-report": "open test-results/reports/test-report.html"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Do not block CI on the custom report — run it as a post-step and upload the output as an artifact. If categorization throws on an unexpected error shape, the exit code should be non-fatal.
|
|
160
|
+
|
|
161
|
+
12. **CI integration.** For intermediate+: PR pipeline runs `npm run smoke` (tag-filtered, not folder-filtered); main merges trigger `npm run exhaustive`; nightly runs `npm run exhaustive` plus a quarantine audit (step 11) reporting quarantined-too-long tests. Record the flake policy (max retries, quarantine threshold) in `harness.config.json` so agents do not silently raise retries to hide flakes.
|
|
162
|
+
|
|
163
|
+
### Phase 4: VALIDATE — Prove the Guards Fire
|
|
164
|
+
|
|
165
|
+
Run the three gates on the clean tree:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
harness validate
|
|
169
|
+
harness check-deps
|
|
170
|
+
npx eslint 'src/**/*.ts' 'tests/**/*.ts'
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
All three must pass before proceeding.
|
|
174
|
+
|
|
175
|
+
**Clean-tree passing is necessary but not sufficient.** All three tools can pass while the rules are silently misconfigured (layer ordering wrong, ESLint files glob missing, forbidden-imports schema fields dropped). Before handing back to `initialize-harness-project` for wrap-up:
|
|
176
|
+
|
|
177
|
+
- Insert one deliberate forbidden import — a sibling-domain import is the easiest (e.g. `src/api/users/users-manager.ts` importing `../auth/auth-manager`). Run `npx eslint <file>` and confirm it reports the violation.
|
|
178
|
+
- Insert one deliberate cross-layer import (e.g. `src/utils/foo.ts` importing from `src/api/users/`). Run `harness check-deps` and confirm it reports the violation.
|
|
179
|
+
- Revert both edits. Confirm the clean tree is green on all three gates.
|
|
180
|
+
|
|
181
|
+
After verification passes, return to `initialize-harness-project`'s Phase 4 for:
|
|
182
|
+
|
|
183
|
+
- `harness scan` (knowledge graph)
|
|
184
|
+
- Roadmap nudge
|
|
185
|
+
- Final commit
|
|
186
|
+
|
|
187
|
+
## Harness Integration
|
|
188
|
+
|
|
189
|
+
- **`initialize-harness-project`** — parent skill. Owns adoption-level selection, `harness init` invocation, persona configuration, AGENTS.md base template, i18n decision, knowledge-graph build, roadmap nudge, final commit.
|
|
190
|
+
- **`harness validate`** — verifies `harness.config.json` schema, AGENTS.md, layers, persona config.
|
|
191
|
+
- **`harness check-deps`** — verifies layer-graph dependency constraints at the file level.
|
|
192
|
+
- **`@harness-engineering/eslint-plugin`** — enforces `forbiddenImports` (same-layer rules) and surfaces layer-graph violations at lint time.
|
|
193
|
+
- **Follow-up test skills** — `test-playwright-setup`, `test-playwright-patterns`, `test-vitest-config`, `test-msw-pattern`, `test-mock-patterns`, `test-factory-patterns`, `harness-test-data`, `api-contract-testing`, `test-contract-testing`.
|
|
194
|
+
- **Related libraries** — `zod-schema-definition` (runtime DTO validation).
|
|
195
|
+
|
|
196
|
+
## Success Criteria
|
|
197
|
+
|
|
198
|
+
- Archetype is recorded in AGENTS.md (API / E2E-UI / Shared library)
|
|
199
|
+
- Shared-library decision is recorded in AGENTS.md
|
|
200
|
+
- Layer model matches the chosen variant (A self-contained or B shared-library consumer) from Phase 3 step 2
|
|
201
|
+
- Layer ordering puts `composition` before `config` (Variant A only)
|
|
202
|
+
- `forbiddenImports` uses only `{from, disallow, message}` — no silently-dropped `exceptPaths`
|
|
203
|
+
- `eslint.config.mjs` declares an explicit `files:` glob and imports a TypeScript parser
|
|
204
|
+
- `.env.example` is present with `REPLACE_ME` placeholders
|
|
205
|
+
- No real secrets are committed (real `.env*` gitignored)
|
|
206
|
+
- Test framework choice and tag taxonomy (including `@smoke` + quarantine tags) are recorded in AGENTS.md
|
|
207
|
+
- Specs are organized `tests/<domain>/<feature>.spec.ts` — no `tests/smoke/` or `tests/regression/` folders
|
|
208
|
+
- `playwright.config.ts` declares html + list + github + json reporters and `grepInvert` for quarantine tags
|
|
209
|
+
- `scripts/generate-reports.ts` exists and is wired to `npm run generate-custom-reports`
|
|
210
|
+
- All three Phase 4 gates pass on the clean tree
|
|
211
|
+
- "Prove the guards fire" step completed — deliberate violations were caught and reverted
|
|
212
|
+
- Control returned to `initialize-harness-project` for knowledge-graph build and final commit
|
|
213
|
+
|
|
214
|
+
## Rationalizations to Reject
|
|
215
|
+
|
|
216
|
+
| Rationalization | Why It Is Wrong |
|
|
217
|
+
| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
218
|
+
| "This is a test suite, so strict layer constraints are overkill" | Test suites benefit _more_ from layer constraints than product code — peer-domain imports and spec coupling are the top sources of flaky, hard-to-maintain suites. |
|
|
219
|
+
| "We can commit a real `.env` for convenience, CI will ignore it" | Phase 3 step 5 forbids committing real credentials. A leaked `.env` in a test repo leaks the same secrets as a product repo. Use `.env.example` with placeholders. |
|
|
220
|
+
| "Tests don't need tags — we'll run everything every time" | Without a `@smoke` tag the PR pipeline grows to 30+ minutes and drives developers to skip CI. Record a tag taxonomy in Phase 3 step 10 even if enforcement comes later. |
|
|
221
|
+
| "We'll split specs into `tests/smoke/` and `tests/regression/` for filtering" | Folder-based filtering forces a file move every time a spec's tier changes. Modern runners (Playwright, Vitest, Cypress) expect `--grep @tag`. Keep `tests/<domain>/<feature>.spec.ts` flat and tag per-test. |
|
|
222
|
+
| "We'll add schema validation later once the client stabilizes" | Runtime DTO validation is the primary contract-drift detector for API test suites. Adding it after tests exist means updating every spec. Decide in Phase 3 step 7. |
|
|
223
|
+
| "We'll copy the API client code into this test suite for convenience" | If a shared API client library already exists, consume it — do not fork. Forked clients drift immediately; the shared library is the contract source of truth. Only scaffold in-repo clients if no shared library exists. See Phase 2. |
|
|
224
|
+
| "Playwright's built-in HTML report is enough" | The built-in report shows a single run. It does not categorize failures (schema vs auth vs timeout), does not track regressions by commit, and does not surface tests quarantined for weeks. Scaffold `scripts/generate-reports.ts` per Phase 3 step 11. |
|
|
225
|
+
| "All three gates passed, so we're done" | Clean-tree passing can co-exist with silently-misconfigured rules (layer ordering wrong, eslint glob missing, forbidden-imports fields dropped). Phase 4 requires deliberately inserting a violation and confirming the tool catches it. |
|
|
226
|
+
|
|
227
|
+
## Examples
|
|
228
|
+
|
|
229
|
+
### Example: Initializing a Shared API Test Library (Intermediate)
|
|
230
|
+
|
|
231
|
+
**CLASSIFY:**
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
Human: "New repo. It's a shared TypeScript HTTP client for our API test suites — consumed by Playwright API tests and also used to mock responses in FE tests. No tests live in this repo."
|
|
235
|
+
package.json has no Playwright/Vitest as direct deps (shared library, not a test runner).
|
|
236
|
+
Archetype: Shared test library.
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**DECIDE (Phase 2):**
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
This is the shared library itself — scaffold in-repo. Phase 2 is trivial.
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**SCAFFOLD (delegated to `initialize-harness-project`):**
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
harness init --level intermediate --language typescript
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**CONFIGURE (Phase 3):**
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
Domain layout: one folder per API domain under src/api/ (challenges, rewards,
|
|
255
|
+
user, oauth, ...). Each domain exposes <domain>-manager.ts taking HttpClient
|
|
256
|
+
in its constructor. Single composition module src/config/managers.ts wires
|
|
257
|
+
every domain from one HttpClient.
|
|
258
|
+
|
|
259
|
+
Layer model (Variant A, harness.config.json):
|
|
260
|
+
utils → src/utils/** (no internal deps)
|
|
261
|
+
composition → src/config/managers.ts → utils, common, config, api
|
|
262
|
+
common → src/api/common/** → utils
|
|
263
|
+
config → src/config/** → utils, common
|
|
264
|
+
api → src/api/** → utils, common, config
|
|
265
|
+
|
|
266
|
+
Layer ordering: composition BEFORE config (first-match-wins).
|
|
267
|
+
|
|
268
|
+
Forbidden (forbiddenImports):
|
|
269
|
+
- any src/api/<domain> importing a sibling src/api/<domain>
|
|
270
|
+
- src/api/common importing config or sibling domains
|
|
271
|
+
|
|
272
|
+
Framework: none in-repo (shared library). Gotcha recorded in AGENTS.md so
|
|
273
|
+
future agents don't scaffold Vitest.
|
|
274
|
+
|
|
275
|
+
Env: .env.example committed with GITHUB_ACCESS_TOKEN placeholder (registry
|
|
276
|
+
auth only). No runtime env vars — consumers pass config explicitly.
|
|
277
|
+
|
|
278
|
+
Auth: OAuth client-credentials with pluggable TokenStorage interface; parent
|
|
279
|
+
vs child scope resolution documented in docs/auth-flow.md. Link to
|
|
280
|
+
a shared test-user library for test-user data.
|
|
281
|
+
|
|
282
|
+
Schema validation: zod at runtime for all response DTOs. Reference
|
|
283
|
+
zod-schema-definition skill for future domain additions.
|
|
284
|
+
|
|
285
|
+
Mocking: expose buildMockResponse / buildMockSuccessResponse /
|
|
286
|
+
buildMockErrorResponse from src/config/mock-response.ts so FE test repos
|
|
287
|
+
can override per spec. Document override contract in docs/mock-response.md.
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**VALIDATE (Phase 4):**
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
harness validate # Pass
|
|
294
|
+
harness check-deps # Pass — no sibling-domain violations
|
|
295
|
+
npx eslint 'src/**/*.ts' # Pass
|
|
296
|
+
|
|
297
|
+
# Prove the guards fire: insert a sibling-domain import, eslint reports it, revert.
|
|
298
|
+
|
|
299
|
+
# Hand back to initialize-harness-project:
|
|
300
|
+
harness scan # Builds .harness/graph/
|
|
301
|
+
git commit -m "feat: initialize harness project at intermediate level for shared API test library"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Example: Playwright API Test Suite Consuming a Shared Library (Intermediate)
|
|
305
|
+
|
|
306
|
+
**CLASSIFY:**
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
Human: "New repo. Playwright API tests for one of our backend services. A shared API client library already exists at @<org>/<team>-testing-api-library and a shared test-user library at @<org>/<team>-testing-user-library."
|
|
310
|
+
package.json will have @playwright/test as a direct dep → test suite signal.
|
|
311
|
+
Archetype: API test suite.
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**DECIDE (Phase 2):**
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
Shared library exists → consume it. Layer variant B (shared-library consumer).
|
|
318
|
+
Do NOT scaffold src/api/. Record decision in AGENTS.md.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**SCAFFOLD (delegated to `initialize-harness-project`):**
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
harness init --level intermediate --language typescript
|
|
325
|
+
# Scaffolded output is a starting point — replace generic layers and eslint config.
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**CONFIGURE (Phase 3, Variant B):**
|
|
329
|
+
|
|
330
|
+
```text
|
|
331
|
+
Dependencies: @<org>/<team>-testing-api-library, @<org>/<team>-testing-user-library,
|
|
332
|
+
@playwright/test, dotenv, zod.
|
|
333
|
+
|
|
334
|
+
Directory layout (no src/api/, no src/page-objects/):
|
|
335
|
+
config/
|
|
336
|
+
api-adapter.ts # Builds Managers from the shared library + env vars
|
|
337
|
+
api-client.ts # Fetcher wrapping Playwright's APIRequestContext
|
|
338
|
+
token-handler.ts # OAuth + test-user token resolution
|
|
339
|
+
constants.ts # TEST_ARTIFACTS_DIR, URLs, etc.
|
|
340
|
+
fixtures/
|
|
341
|
+
test-fixture.ts # Playwright fixture exposing {api, user}
|
|
342
|
+
test-no-init-auth-fixture.ts # Fixture for 401/auth-failure tests
|
|
343
|
+
expects.ts # expectOkResponse, expectUnauthorized, ...
|
|
344
|
+
tests/
|
|
345
|
+
challenges/
|
|
346
|
+
create.spec.ts
|
|
347
|
+
checkin.spec.ts
|
|
348
|
+
...
|
|
349
|
+
oauth/
|
|
350
|
+
login.spec.ts
|
|
351
|
+
user-profile/
|
|
352
|
+
...
|
|
353
|
+
global.setup.ts
|
|
354
|
+
global.teardown.ts
|
|
355
|
+
scripts/
|
|
356
|
+
generate-reports.ts
|
|
357
|
+
playwright.config.ts
|
|
358
|
+
.env.example
|
|
359
|
+
harness.config.json
|
|
360
|
+
AGENTS.md
|
|
361
|
+
|
|
362
|
+
Layer model (Variant B, harness.config.json):
|
|
363
|
+
utils → src/utils/** (no internal deps)
|
|
364
|
+
config → config/** → utils
|
|
365
|
+
fixtures → fixtures/** → utils, config
|
|
366
|
+
specs → tests/** → utils, config, fixtures
|
|
367
|
+
|
|
368
|
+
Forbidden (same-layer or cross-cutting):
|
|
369
|
+
- tests/** importing @<org>/<team>-testing-api-library directly
|
|
370
|
+
(must go through fixtures → config adapter)
|
|
371
|
+
- fixtures/** importing tests/**
|
|
372
|
+
- Specs importing each other
|
|
373
|
+
|
|
374
|
+
Tags (playwright.config.ts):
|
|
375
|
+
grepInvert: [/@known-failure/, /@wip/, /@blocked/, /@archived/]
|
|
376
|
+
Tag @smoke on PR-gate specs; untagged = regression.
|
|
377
|
+
|
|
378
|
+
Reporters (playwright.config.ts):
|
|
379
|
+
['html', {outputFolder: './test-results/html-test-results', open: 'never'}],
|
|
380
|
+
['list'],
|
|
381
|
+
['github'],
|
|
382
|
+
['json', {outputFile: 'test-results/json-results/results.json'}],
|
|
383
|
+
|
|
384
|
+
Custom report (scripts/generate-reports.ts):
|
|
385
|
+
Reads test-results/json-results/results.json. Emits HTML + Slack with:
|
|
386
|
+
failure categorization, per-area health, delta vs history, quarantine ledger.
|
|
387
|
+
Wired to `npm run generate-custom-reports` / `npm run show-custom-report`.
|
|
388
|
+
|
|
389
|
+
package.json scripts:
|
|
390
|
+
smoke: playwright test --grep @smoke
|
|
391
|
+
exhaustive: playwright test
|
|
392
|
+
list: playwright test --list
|
|
393
|
+
generate-custom-reports: npx ts-node scripts/generate-reports.ts
|
|
394
|
+
show-custom-report: open test-results/reports/test-report.html
|
|
395
|
+
|
|
396
|
+
.env.example: API_BASE_URL, OAUTH_TOKEN_URL, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET,
|
|
397
|
+
TEST_USER_POOL_URL, TEST_USER_POOL_TOKEN. Real .env is gitignored.
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**VALIDATE (Phase 4):**
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
harness validate # Pass
|
|
404
|
+
harness check-deps # Pass
|
|
405
|
+
npm run lint # Pass
|
|
406
|
+
npm run smoke # Sanity: runs only @smoke-tagged specs
|
|
407
|
+
|
|
408
|
+
# Prove the forbidden-imports rule fires:
|
|
409
|
+
# temporarily add an import of @<org>/<team>-testing-api-library to a spec
|
|
410
|
+
npx eslint tests/challenges/create.spec.ts # Should report violation
|
|
411
|
+
# revert, confirm green
|
|
412
|
+
|
|
413
|
+
# Hand back to initialize-harness-project:
|
|
414
|
+
git commit -m "feat: initialize harness project at intermediate level for Playwright API suite"
|
|
415
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: initialize-test-suite-project
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Scaffold or migrate a test-suite project (API, E2E/UI, or shared library) with test-suite-specific layer models, tags, reporter stack, and custom report
|
|
4
|
+
stability: static
|
|
5
|
+
cognitive_mode: constructive-architect
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
- cursor
|
|
12
|
+
- codex
|
|
13
|
+
tools:
|
|
14
|
+
- Bash
|
|
15
|
+
- Read
|
|
16
|
+
- Write
|
|
17
|
+
- Glob
|
|
18
|
+
cli:
|
|
19
|
+
command: harness skill run initialize-test-suite-project
|
|
20
|
+
args:
|
|
21
|
+
- name: path
|
|
22
|
+
description: Project root path
|
|
23
|
+
required: false
|
|
24
|
+
mcp:
|
|
25
|
+
tool: run_skill
|
|
26
|
+
input:
|
|
27
|
+
skill: initialize-test-suite-project
|
|
28
|
+
path: string
|
|
29
|
+
type: flexible
|
|
30
|
+
tier: 1
|
|
31
|
+
state:
|
|
32
|
+
persistent: false
|
|
33
|
+
files: []
|
|
34
|
+
depends_on:
|
|
35
|
+
- initialize-harness-project
|
|
@@ -114,9 +114,31 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
114
114
|
|
|
115
115
|
3. **Write the spec** to `docs/changes/<feature>/proposal.md`.
|
|
116
116
|
|
|
117
|
-
4. **Run
|
|
117
|
+
4. **Run skill advisor scan.** After writing the spec, extract signals from its content and scan the skill index for relevant skills. Write results to `docs/changes/<feature>/SKILLS.md` alongside the spec.
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
Use the `advise_skills` MCP tool:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
advise_skills({
|
|
123
|
+
"path": "<project-root>",
|
|
124
|
+
"specPath": "docs/changes/<feature>/proposal.md"
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Announce findings in a brief summary (skip announcement in `--fast` mode):
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Skill Advisor: Found N relevant skills for '<feature>'
|
|
132
|
+
Apply: N (skill-a, skill-b, ...)
|
|
133
|
+
Reference: N | Consider: N
|
|
134
|
+
Full list: docs/changes/<feature>/SKILLS.md
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
In `--thorough` mode, show the full skill list for human review before proceeding.
|
|
138
|
+
|
|
139
|
+
5. **Run `harness validate`** to verify proper placement and project health.
|
|
140
|
+
|
|
141
|
+
6. **Request sign-off via `emit_interaction`:**
|
|
120
142
|
|
|
121
143
|
```json
|
|
122
144
|
emit_interaction({
|
|
@@ -133,14 +155,14 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
133
155
|
|
|
134
156
|
The human must explicitly approve before this skill is complete.
|
|
135
157
|
|
|
136
|
-
|
|
158
|
+
7. **Add feature to roadmap.** If `docs/roadmap.md` exists:
|
|
137
159
|
- Derive feature name from the spec title (the H1 heading).
|
|
138
160
|
- Call `manage_roadmap` with action `add`, `status: "planned"`, `milestone: "Current Work"`, and the spec path.
|
|
139
161
|
- If the feature already exists, skip silently.
|
|
140
162
|
- If `manage_roadmap` is unavailable, fall back to `parseRoadmap`/`serializeRoadmap` from core. Warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored."
|
|
141
163
|
- If no roadmap exists, skip silently.
|
|
142
164
|
|
|
143
|
-
|
|
165
|
+
8. **Write handoff and suggest transition.** After approval:
|
|
144
166
|
|
|
145
167
|
Write handoff to the session-scoped path when a session slug is known, otherwise fall back to the global path:
|
|
146
168
|
- Session-scoped (preferred): `.harness/sessions/<session-slug>/handoff.json`
|
|
@@ -155,7 +177,13 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
155
177
|
"summary": "<1-sentence summary>",
|
|
156
178
|
"artifacts": ["<spec path>"],
|
|
157
179
|
"decisions": [{ "what": "<decision>", "why": "<rationale>" }],
|
|
158
|
-
"contextKeywords": ["<keywords from Phase 2>"]
|
|
180
|
+
"contextKeywords": ["<keywords from Phase 2>"],
|
|
181
|
+
"recommendedSkills": {
|
|
182
|
+
"apply": ["<skill-names>"],
|
|
183
|
+
"reference": ["<skill-names>"],
|
|
184
|
+
"consider": ["<skill-names>"],
|
|
185
|
+
"skillsPath": "docs/changes/<feature>/SKILLS.md"
|
|
186
|
+
}
|
|
159
187
|
}
|
|
160
188
|
```
|
|
161
189
|
|
|
@@ -96,6 +96,12 @@ For each task, starting from current position:
|
|
|
96
96
|
|
|
97
97
|
1. **Read task instructions completely** before writing any code.
|
|
98
98
|
|
|
99
|
+
1b. **Load skill context for annotated tasks.** If the task has a `**Skills:**` annotation:
|
|
100
|
+
|
|
101
|
+
- For `apply` tier skills: note the skill name in the task context. The skill may provide patterns or approaches to follow during implementation.
|
|
102
|
+
- For `reference` tier skills (type: `knowledge`): load the skill's SKILL.md content as supplementary context. Cap at 3 reference skills per task to manage context budget.
|
|
103
|
+
- Use the skill content to inform implementation decisions but follow the plan's exact instructions as written. Skill context provides background knowledge, not overriding instructions.
|
|
104
|
+
|
|
99
105
|
2. **Follow instructions exactly.** The plan contains exact file paths, code, and commands. Execute as written.
|
|
100
106
|
|
|
101
107
|
3. **TDD rhythm:**
|