@harness-engineering/cli 1.13.0 → 1.13.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/claude-code/add-harness-component/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/align-documentation/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/check-mechanical-constraints/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/detect-doc-drift/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-api-design/SKILL.md +304 -0
- package/dist/agents/skills/claude-code/harness-api-design/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-architecture-advisor/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-auth/SKILL.md +279 -0
- package/dist/agents/skills/claude-code/harness-auth/skill.yaml +81 -0
- package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-caching/SKILL.md +309 -0
- package/dist/agents/skills/claude-code/harness-caching/skill.yaml +73 -0
- package/dist/agents/skills/claude-code/harness-chaos/SKILL.md +295 -0
- package/dist/agents/skills/claude-code/harness-chaos/skill.yaml +72 -0
- package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-compliance/SKILL.md +303 -0
- package/dist/agents/skills/claude-code/harness-compliance/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-containerization/SKILL.md +284 -0
- package/dist/agents/skills/claude-code/harness-containerization/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-data-pipeline/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-data-pipeline/skill.yaml +81 -0
- package/dist/agents/skills/claude-code/harness-data-validation/SKILL.md +343 -0
- package/dist/agents/skills/claude-code/harness-data-validation/skill.yaml +75 -0
- package/dist/agents/skills/claude-code/harness-database/SKILL.md +258 -0
- package/dist/agents/skills/claude-code/harness-database/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-debugging/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-deployment/SKILL.md +255 -0
- package/dist/agents/skills/claude-code/harness-deployment/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-design/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-diagnostics/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-dx/SKILL.md +276 -0
- package/dist/agents/skills/claude-code/harness-dx/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-e2e/SKILL.md +245 -0
- package/dist/agents/skills/claude-code/harness-e2e/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-event-driven/SKILL.md +280 -0
- package/dist/agents/skills/claude-code/harness-event-driven/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-feature-flags/SKILL.md +287 -0
- package/dist/agents/skills/claude-code/harness-feature-flags/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-git-workflow/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-impact-analysis/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-incident-response/SKILL.md +223 -0
- package/dist/agents/skills/claude-code/harness-incident-response/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-infrastructure-as-code/SKILL.md +279 -0
- package/dist/agents/skills/claude-code/harness-infrastructure-as-code/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-integration-test/SKILL.md +271 -0
- package/dist/agents/skills/claude-code/harness-integration-test/skill.yaml +73 -0
- package/dist/agents/skills/claude-code/harness-integrity/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-load-testing/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-load-testing/skill.yaml +79 -0
- package/dist/agents/skills/claude-code/harness-ml-ops/SKILL.md +341 -0
- package/dist/agents/skills/claude-code/harness-ml-ops/skill.yaml +79 -0
- package/dist/agents/skills/claude-code/harness-mobile-patterns/SKILL.md +326 -0
- package/dist/agents/skills/claude-code/harness-mobile-patterns/skill.yaml +82 -0
- package/dist/agents/skills/claude-code/harness-mutation-test/SKILL.md +251 -0
- package/dist/agents/skills/claude-code/harness-mutation-test/skill.yaml +70 -0
- package/dist/agents/skills/claude-code/harness-observability/SKILL.md +283 -0
- package/dist/agents/skills/claude-code/harness-observability/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-onboarding/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-parallel-agents/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-perf/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-perf-tdd/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-planning/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-pre-commit-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-product-spec/SKILL.md +285 -0
- package/dist/agents/skills/claude-code/harness-product-spec/skill.yaml +72 -0
- package/dist/agents/skills/claude-code/harness-property-test/SKILL.md +281 -0
- package/dist/agents/skills/claude-code/harness-property-test/skill.yaml +71 -0
- package/dist/agents/skills/claude-code/harness-refactoring/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-release-readiness/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-resilience/SKILL.md +255 -0
- package/dist/agents/skills/claude-code/harness-resilience/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-secrets/SKILL.md +293 -0
- package/dist/agents/skills/claude-code/harness-secrets/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-skill-authoring/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-sql-review/SKILL.md +315 -0
- package/dist/agents/skills/claude-code/harness-sql-review/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-state-management/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-tdd/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-test-data/SKILL.md +268 -0
- package/dist/agents/skills/claude-code/harness-test-data/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-ux-copy/SKILL.md +271 -0
- package/dist/agents/skills/claude-code/harness-ux-copy/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-verify/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-visual-regression/SKILL.md +257 -0
- package/dist/agents/skills/claude-code/harness-visual-regression/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/validate-context-engineering/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-api-design/SKILL.md +304 -0
- package/dist/agents/skills/gemini-cli/harness-api-design/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-auth/SKILL.md +279 -0
- package/dist/agents/skills/gemini-cli/harness-auth/skill.yaml +81 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-caching/SKILL.md +309 -0
- package/dist/agents/skills/gemini-cli/harness-caching/skill.yaml +73 -0
- package/dist/agents/skills/gemini-cli/harness-chaos/SKILL.md +295 -0
- package/dist/agents/skills/gemini-cli/harness-chaos/skill.yaml +72 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-compliance/SKILL.md +303 -0
- package/dist/agents/skills/gemini-cli/harness-compliance/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-containerization/SKILL.md +284 -0
- package/dist/agents/skills/gemini-cli/harness-containerization/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-data-pipeline/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-data-pipeline/skill.yaml +81 -0
- package/dist/agents/skills/gemini-cli/harness-data-validation/SKILL.md +343 -0
- package/dist/agents/skills/gemini-cli/harness-data-validation/skill.yaml +75 -0
- package/dist/agents/skills/gemini-cli/harness-database/SKILL.md +258 -0
- package/dist/agents/skills/gemini-cli/harness-database/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-deployment/SKILL.md +255 -0
- package/dist/agents/skills/gemini-cli/harness-deployment/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-dx/SKILL.md +276 -0
- package/dist/agents/skills/gemini-cli/harness-dx/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-e2e/SKILL.md +245 -0
- package/dist/agents/skills/gemini-cli/harness-e2e/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-event-driven/SKILL.md +280 -0
- package/dist/agents/skills/gemini-cli/harness-event-driven/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-feature-flags/SKILL.md +287 -0
- package/dist/agents/skills/gemini-cli/harness-feature-flags/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-incident-response/SKILL.md +223 -0
- package/dist/agents/skills/gemini-cli/harness-incident-response/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/SKILL.md +279 -0
- package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-integration-test/SKILL.md +271 -0
- package/dist/agents/skills/gemini-cli/harness-integration-test/skill.yaml +73 -0
- package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-load-testing/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-load-testing/skill.yaml +79 -0
- package/dist/agents/skills/gemini-cli/harness-ml-ops/SKILL.md +341 -0
- package/dist/agents/skills/gemini-cli/harness-ml-ops/skill.yaml +79 -0
- package/dist/agents/skills/gemini-cli/harness-mobile-patterns/SKILL.md +326 -0
- package/dist/agents/skills/gemini-cli/harness-mobile-patterns/skill.yaml +82 -0
- package/dist/agents/skills/gemini-cli/harness-mutation-test/SKILL.md +251 -0
- package/dist/agents/skills/gemini-cli/harness-mutation-test/skill.yaml +70 -0
- package/dist/agents/skills/gemini-cli/harness-observability/SKILL.md +283 -0
- package/dist/agents/skills/gemini-cli/harness-observability/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-perf-tdd/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-product-spec/SKILL.md +285 -0
- package/dist/agents/skills/gemini-cli/harness-product-spec/skill.yaml +72 -0
- package/dist/agents/skills/gemini-cli/harness-property-test/SKILL.md +281 -0
- package/dist/agents/skills/gemini-cli/harness-property-test/skill.yaml +71 -0
- package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-release-readiness/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-resilience/SKILL.md +255 -0
- package/dist/agents/skills/gemini-cli/harness-resilience/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-secrets/SKILL.md +293 -0
- package/dist/agents/skills/gemini-cli/harness-secrets/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/SKILL.md +240 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-sql-review/SKILL.md +315 -0
- package/dist/agents/skills/gemini-cli/harness-sql-review/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-test-data/SKILL.md +268 -0
- package/dist/agents/skills/gemini-cli/harness-test-data/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-ux-copy/SKILL.md +271 -0
- package/dist/agents/skills/gemini-cli/harness-ux-copy/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-visual-regression/SKILL.md +257 -0
- package/dist/agents/skills/gemini-cli/harness-visual-regression/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +1 -0
- package/dist/{agents-md-P2RHSUV7.js → agents-md-XU3BHE22.js} +1 -1
- package/dist/{architecture-ESOOE26S.js → architecture-2R5Z4ZAF.js} +2 -2
- package/dist/bin/harness-mcp.js +14 -13
- package/dist/bin/harness.js +22 -21
- package/dist/{check-phase-gate-S2MZKLFQ.js → check-phase-gate-2OFZ7OWW.js} +3 -2
- package/dist/{chunk-LD3DKUK5.js → chunk-4ZMOCPYO.js} +1 -1
- package/dist/{chunk-5VY23YK3.js → chunk-65FRIL4D.js} +2 -2
- package/dist/{chunk-L2KLU56K.js → chunk-AOZRDOIP.js} +2 -2
- package/dist/{chunk-MACVXDZK.js → chunk-DZS7CJKL.js} +4 -4
- package/dist/{chunk-7PZWR4LI.js → chunk-IM32EEDM.js} +9 -9
- package/dist/{chunk-2YPZKGAG.js → chunk-IMFVFNJE.js} +1 -1
- package/dist/{chunk-HD4IBGLA.js → chunk-N5G5QMS3.js} +24 -1
- package/dist/{chunk-MI5XJQDY.js → chunk-ND6PNADU.js} +23 -9
- package/dist/{chunk-7KQSUZVG.js → chunk-NERR4TAO.js} +729 -436
- package/dist/{chunk-PSNN4LWX.js → chunk-NOPU4RZ4.js} +2 -2
- package/dist/{chunk-KELT6K6M.js → chunk-PQ5YK4AY.js} +287 -258
- package/dist/{chunk-WPPDRIJL.js → chunk-QY4T6YAZ.js} +3 -3
- package/dist/{chunk-RZSUJBZZ.js → chunk-SSKDAOX5.js} +31 -28
- package/dist/{chunk-2VU4MFM3.js → chunk-TKJZKICB.js} +6 -6
- package/dist/{chunk-GNGELAXY.js → chunk-TS3XWPW5.js} +1 -1
- package/dist/chunk-UAX4I5ZE.js +217 -0
- package/dist/{chunk-VRFZWGMS.js → chunk-XYLGHKG6.js} +5 -1
- package/dist/{chunk-6N4R6FVX.js → chunk-YBJ262QL.js} +1 -1
- package/dist/{chunk-3KOLLWWE.js → chunk-Z77YQRQT.js} +11 -207
- package/dist/{ci-workflow-4NYBUG6R.js → ci-workflow-EHV65NQB.js} +1 -1
- package/dist/{create-skill-WPXHSLX2.js → create-skill-XSWHMSM5.js} +2 -2
- package/dist/{dist-WF4C7A4A.js → dist-2B363XUH.js} +1 -1
- package/dist/{dist-M6BQODWC.js → dist-HXHWB7SV.js} +2 -2
- package/dist/{docs-BPYCN2DR.js → docs-FZOPM4GK.js} +4 -2
- package/dist/{engine-LXLIWQQ3.js → engine-OL4T6NZS.js} +1 -1
- package/dist/{entropy-4VDVV5CR.js → entropy-LVHJMFGH.js} +2 -2
- package/dist/{feedback-63QB5RCA.js → feedback-IHLVLMRD.js} +1 -1
- package/dist/{generate-agent-definitions-QABOJG56.js → generate-agent-definitions-64S3CLEZ.js} +3 -3
- package/dist/{glob-helper-5OHBUQAI.js → glob-helper-R5FXNUPS.js} +1 -1
- package/dist/{graph-loader-KO4GJ5N2.js → graph-loader-GJZ4FN4Y.js} +1 -1
- package/dist/index.d.ts +35 -8
- package/dist/index.js +23 -21
- package/dist/{loader-Z2IT7QX3.js → loader-DPYFB6R6.js} +1 -1
- package/dist/{mcp-KQHEL5IF.js → mcp-JQUI7BVZ.js} +14 -13
- package/dist/{performance-26BH47O4.js → performance-ZTVSUANN.js} +2 -2
- package/dist/{review-pipeline-GHR3WFBI.js → review-pipeline-76JHKGSV.js} +1 -1
- package/dist/{runtime-PDWD7UIK.js → runtime-X7U6SC7K.js} +1 -1
- package/dist/{security-UQFUZXEN.js → security-FWQZF2IZ.js} +1 -1
- package/dist/skill-executor-XZLYZYAK.js +8 -0
- package/dist/{validate-N7QJOKFZ.js → validate-GCHZJIL7.js} +2 -2
- package/dist/{validate-cross-check-EDQ5QGTM.js → validate-cross-check-STFHYMAZ.js} +1 -1
- package/package.json +3 -3
- package/dist/skill-executor-RG45LUO5.js +0 -8
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# Harness Mobile Patterns
|
|
2
|
+
|
|
3
|
+
> Advise on mobile platform lifecycle management, permission handling, deep linking, push notifications, and app store submission compliance. Covers iOS, Android, React Native, and Flutter with platform-specific best practices.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- When building or reviewing a mobile feature that involves permissions, deep links, or push notifications
|
|
8
|
+
- When preparing a mobile application for App Store or Play Store submission
|
|
9
|
+
- When auditing an existing mobile app for platform lifecycle and configuration correctness
|
|
10
|
+
- NOT for mobile UI design patterns or component libraries (use harness-design-mobile)
|
|
11
|
+
- NOT for mobile accessibility auditing (use harness-accessibility)
|
|
12
|
+
- NOT for mobile performance profiling or bundle size analysis (use harness-perf)
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
### Phase 1: DETECT -- Identify Mobile Platform and Configuration
|
|
17
|
+
|
|
18
|
+
1. **Resolve project root.** Use provided path or cwd.
|
|
19
|
+
|
|
20
|
+
2. **Detect mobile platform and framework.** Scan for:
|
|
21
|
+
- **React Native:** `app.json`, `App.tsx`, `react-native.config.js`, `node_modules/react-native`
|
|
22
|
+
- **Flutter:** `pubspec.yaml`, `lib/main.dart`, `android/`, `ios/`
|
|
23
|
+
- **Native iOS:** `*.xcodeproj`, `*.xcworkspace`, `Info.plist`, `AppDelegate.swift`
|
|
24
|
+
- **Native Android:** `AndroidManifest.xml`, `build.gradle`, `*.kt` or `*.java` in `app/src/`
|
|
25
|
+
- **Expo:** `app.json` with `expo` key, `eas.json`, `expo-modules-autolinking`
|
|
26
|
+
|
|
27
|
+
3. **Inventory platform configurations.** Read and catalog:
|
|
28
|
+
- **iOS:** `Info.plist` (permissions, URL schemes, associated domains), `Entitlements.plist`, provisioning profile references
|
|
29
|
+
- **Android:** `AndroidManifest.xml` (permissions, intent filters, deep links), `build.gradle` (target SDK, dependencies), `google-services.json`
|
|
30
|
+
- **React Native:** `app.json` (display name, bundle ID), native module links, Podfile
|
|
31
|
+
- **Flutter:** `pubspec.yaml` (dependencies), platform-specific configs under `ios/` and `android/`
|
|
32
|
+
|
|
33
|
+
4. **Detect feature implementations.** Scan source code for:
|
|
34
|
+
- **Permissions:** `requestPermission`, `checkPermission`, `NSLocationWhenInUseUsageDescription`, `uses-permission`
|
|
35
|
+
- **Deep linking:** URL scheme handlers, universal link configuration, App Links verification, `Linking.addEventListener`
|
|
36
|
+
- **Push notifications:** Firebase Cloud Messaging setup, APNs configuration, notification handling code
|
|
37
|
+
- **Lifecycle:** `AppState.addEventListener`, `onPause/onResume`, `WidgetsBindingObserver`, `applicationDidEnterBackground`
|
|
38
|
+
|
|
39
|
+
5. **Check build and signing configuration.** Verify:
|
|
40
|
+
- Bundle identifier / application ID consistency across configs
|
|
41
|
+
- Version number and build number format
|
|
42
|
+
- Signing configuration references (keystore for Android, certificates for iOS)
|
|
43
|
+
- Build variants (debug, release, staging)
|
|
44
|
+
|
|
45
|
+
6. **Report detection summary:**
|
|
46
|
+
```
|
|
47
|
+
Mobile Platform Detection:
|
|
48
|
+
Framework: React Native 0.73 (Expo managed workflow)
|
|
49
|
+
Platforms: iOS 15+ (deployment target), Android API 24+ (minSdkVersion)
|
|
50
|
+
Bundle ID: com.example.myapp (consistent across platforms)
|
|
51
|
+
Permissions: camera, photo library, push notifications, location (when in use)
|
|
52
|
+
Deep linking: URL scheme registered, universal links not configured
|
|
53
|
+
Push: Firebase Cloud Messaging (Android), APNs (iOS)
|
|
54
|
+
Build: 3 variants (debug, staging, release)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Phase 2: ANALYZE -- Evaluate Platform Patterns
|
|
60
|
+
|
|
61
|
+
1. **Audit permission handling.** For each declared permission:
|
|
62
|
+
- Is the permission requested at the point of use (not at app launch)?
|
|
63
|
+
- Is there a pre-permission prompt explaining why it is needed?
|
|
64
|
+
- Is the denied state handled gracefully? (fallback UI, re-request with rationale)
|
|
65
|
+
- Is the permission usage description string clear and specific?
|
|
66
|
+
- **iOS:** Are `NSUsageDescription` strings present for every requested permission?
|
|
67
|
+
- **Android:** Is the runtime permission flow implemented for dangerous permissions (API 23+)?
|
|
68
|
+
- **EARS pattern:** When the user denies camera permission, the system shall display a fallback UI explaining why the camera is needed and offer a button to open Settings.
|
|
69
|
+
|
|
70
|
+
2. **Audit deep linking.** Evaluate:
|
|
71
|
+
- **URL scheme:** Is a custom scheme registered? (`myapp://`) Are conflicts possible with other apps?
|
|
72
|
+
- **Universal Links (iOS):** Is the `apple-app-site-association` file configured? Is `applinks:` domain in entitlements?
|
|
73
|
+
- **App Links (Android):** Is the `intent-filter` with `autoVerify="true"` configured? Is `assetlinks.json` hosted?
|
|
74
|
+
- **Navigation:** Do deep links route to the correct screen? Is authentication state handled? (deep link to protected content when logged out)
|
|
75
|
+
- **Fallback:** What happens when the app is not installed? Is there a web fallback or app store redirect?
|
|
76
|
+
|
|
77
|
+
3. **Audit push notification setup.** Evaluate:
|
|
78
|
+
- Is push token registration handled at the right time? (after permission granted, not at startup)
|
|
79
|
+
- Are notification payloads handled in all app states? (foreground, background, terminated)
|
|
80
|
+
- Is the notification tap handler routing to the correct screen?
|
|
81
|
+
- Are silent/background notifications handled separately from display notifications?
|
|
82
|
+
- **iOS:** Is the APNs environment correct? (sandbox for dev, production for release)
|
|
83
|
+
- **Android:** Are notification channels created for API 26+? Are channel importance levels appropriate?
|
|
84
|
+
|
|
85
|
+
4. **Audit lifecycle management.** Check:
|
|
86
|
+
- Is app state change handled? (foreground, background, inactive/paused)
|
|
87
|
+
- Are WebSocket connections and location updates paused when backgrounded?
|
|
88
|
+
- Is local state persisted before backgrounding? (in-progress forms, drafts)
|
|
89
|
+
- Are long-running tasks configured for background execution? (iOS: background modes, Android: WorkManager)
|
|
90
|
+
- Is the splash screen / launch screen configured to avoid white flash?
|
|
91
|
+
|
|
92
|
+
5. **Audit app store readiness.** Check:
|
|
93
|
+
- **iOS App Store:** Privacy nutrition labels match actual data collection, required screenshots and metadata
|
|
94
|
+
- **Google Play Store:** Data safety section accuracy, target API level compliance (Play requires API 34+)
|
|
95
|
+
- **Both:** Privacy policy URL configured, age rating appropriate, content declarations accurate
|
|
96
|
+
- **Version requirements:** Does the app meet minimum OS version requirements for store submission?
|
|
97
|
+
|
|
98
|
+
6. **Classify findings by severity:**
|
|
99
|
+
- **Error:** Missing permission usage description (App Store rejection), deep link to authenticated content without auth check, push token sent to server without encryption
|
|
100
|
+
- **Warning:** Permissions requested at launch instead of point-of-use, missing universal link fallback, notification channels not created
|
|
101
|
+
- **Info:** Optional background mode not configured, missing pre-permission prompt, version number format suggestion
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### Phase 3: ADVISE -- Recommend Platform Best Practices
|
|
106
|
+
|
|
107
|
+
1. **Generate permission handling recommendations.** For each finding:
|
|
108
|
+
- Provide the platform-specific fix with code reference
|
|
109
|
+
- Show the recommended permission flow (request -> explain -> handle denial -> Settings redirect)
|
|
110
|
+
- Include usage description string recommendations that explain user benefit, not technical need
|
|
111
|
+
- Example: Instead of "This app needs camera access" use "Take photos to add to your project boards"
|
|
112
|
+
|
|
113
|
+
2. **Generate deep linking setup guide.** Based on what is missing:
|
|
114
|
+
- **Universal Links:** Provide `apple-app-site-association` template, entitlement configuration, and server-side hosting instructions
|
|
115
|
+
- **App Links:** Provide `assetlinks.json` template, `intent-filter` XML, and verification steps
|
|
116
|
+
- **Deferred deep linking:** Recommend solutions for handling links when the app is not installed (Branch, Firebase Dynamic Links successor, or custom implementation)
|
|
117
|
+
- Include routing logic for handling authentication state during deep link navigation
|
|
118
|
+
|
|
119
|
+
3. **Generate push notification checklist.** Provide:
|
|
120
|
+
- Platform-specific setup steps (FCM for Android, APNs for iOS)
|
|
121
|
+
- Notification handler implementation for all app states
|
|
122
|
+
- Channel creation code for Android API 26+
|
|
123
|
+
- Token refresh handling and server-side update logic
|
|
124
|
+
- Testing strategy (push notification testing is notoriously difficult)
|
|
125
|
+
|
|
126
|
+
4. **Generate store submission checklist.** Provide:
|
|
127
|
+
- Privacy manifest requirements (iOS 17+: required reason APIs, tracking declaration)
|
|
128
|
+
- Data safety form guidance (Google Play: data collection, sharing, security practices)
|
|
129
|
+
- Screenshot and metadata requirements per platform
|
|
130
|
+
- Common rejection reasons and how to avoid them
|
|
131
|
+
|
|
132
|
+
5. **Recommend lifecycle improvements.** Provide:
|
|
133
|
+
- State preservation patterns for the detected framework
|
|
134
|
+
- Background task configuration for long-running operations
|
|
135
|
+
- Memory management recommendations (clearing caches on memory warning)
|
|
136
|
+
- Network reconnection patterns after backgrounding
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### Phase 4: VALIDATE -- Verify Configuration Completeness
|
|
141
|
+
|
|
142
|
+
1. **Verify permission configuration completeness.** For each permission in code:
|
|
143
|
+
- Is the permission declared in the platform manifest? (Info.plist / AndroidManifest.xml)
|
|
144
|
+
- Is the runtime request implemented? (not just the manifest declaration)
|
|
145
|
+
- Is the denial handler implemented?
|
|
146
|
+
- Does the usage description match the actual use case?
|
|
147
|
+
|
|
148
|
+
2. **Verify deep link routing.** For each registered deep link pattern:
|
|
149
|
+
- Does a route handler exist that matches the URL pattern?
|
|
150
|
+
- Is the handler accessible from all app states? (cold start, warm start, foreground)
|
|
151
|
+
- Are URL parameters validated before use?
|
|
152
|
+
|
|
153
|
+
3. **Verify push notification flow.** End-to-end:
|
|
154
|
+
- Permission request -> token registration -> server-side storage -> notification receipt -> tap handling -> screen navigation
|
|
155
|
+
- Each step must be implemented, not just the first and last
|
|
156
|
+
|
|
157
|
+
4. **Output mobile patterns report:**
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
Mobile Patterns Report: [PASS/NEEDS_ATTENTION/FAIL]
|
|
161
|
+
Platform: React Native 0.73 (iOS + Android)
|
|
162
|
+
|
|
163
|
+
Permissions (4 declared):
|
|
164
|
+
camera: OK (point-of-use request, denial handled, description clear)
|
|
165
|
+
location: WARNING (requested at launch, should be point-of-use)
|
|
166
|
+
push: OK (requested after onboarding, token registered)
|
|
167
|
+
photo_library: ERROR (missing NSPhotoLibraryUsageDescription in Info.plist)
|
|
168
|
+
|
|
169
|
+
Deep Linking:
|
|
170
|
+
URL scheme: OK (myapp:// registered on both platforms)
|
|
171
|
+
Universal Links: NOT_CONFIGURED (recommended for iOS)
|
|
172
|
+
App Links: NOT_CONFIGURED (recommended for Android)
|
|
173
|
+
Auth handling: WARNING (deep link to /profile without auth check)
|
|
174
|
+
|
|
175
|
+
Push Notifications:
|
|
176
|
+
iOS (APNs): OK
|
|
177
|
+
Android (FCM): WARNING (no notification channels for API 26+)
|
|
178
|
+
Foreground handling: OK
|
|
179
|
+
Background handling: OK
|
|
180
|
+
Terminated handling: MISSING
|
|
181
|
+
|
|
182
|
+
Store Readiness:
|
|
183
|
+
iOS: NEEDS_ATTENTION (missing privacy nutrition labels for location)
|
|
184
|
+
Android: NEEDS_ATTENTION (target SDK 33, Play Store requires 34+)
|
|
185
|
+
|
|
186
|
+
ERRORS: 1 | WARNINGS: 4 | INFO: 2
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
5. **Cross-reference platform configs.** Verify iOS and Android configurations are consistent:
|
|
190
|
+
- Same deep link patterns registered on both platforms
|
|
191
|
+
- Same permissions requested on both platforms (where applicable)
|
|
192
|
+
- Same push notification handling on both platforms
|
|
193
|
+
- Version numbers aligned
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Harness Integration
|
|
198
|
+
|
|
199
|
+
- **`harness skill run harness-mobile-patterns`** -- Primary command for mobile platform auditing.
|
|
200
|
+
- **`harness validate`** -- Run after applying configuration changes to verify project health.
|
|
201
|
+
- **`Glob`** -- Used to locate platform configs (Info.plist, AndroidManifest.xml), native modules, and framework files.
|
|
202
|
+
- **`Grep`** -- Used to find permission requests, deep link handlers, notification setup, and lifecycle methods in source code.
|
|
203
|
+
- **`Read`** -- Used to read platform manifests, entitlements, build configurations, and native module source.
|
|
204
|
+
- **`Write`** -- Used to generate configuration templates, `apple-app-site-association` files, and store submission checklists.
|
|
205
|
+
- **`Bash`** -- Used to check Xcode project settings, Gradle configurations, and run platform-specific validation commands.
|
|
206
|
+
- **`emit_interaction`** -- Used to present the audit report and confirm recommendations before generating configuration changes.
|
|
207
|
+
|
|
208
|
+
## Success Criteria
|
|
209
|
+
|
|
210
|
+
- Mobile platform and framework are correctly detected with version information
|
|
211
|
+
- All declared permissions are audited for request timing, denial handling, and description quality
|
|
212
|
+
- Deep linking configuration is evaluated for both URL schemes and universal/app links
|
|
213
|
+
- Push notification setup covers all app states (foreground, background, terminated)
|
|
214
|
+
- Lifecycle management is evaluated for state preservation and background behavior
|
|
215
|
+
- App store readiness is assessed against current submission requirements
|
|
216
|
+
- Report provides platform-specific, actionable findings with code references
|
|
217
|
+
|
|
218
|
+
## Examples
|
|
219
|
+
|
|
220
|
+
### Example: React Native App with Expo
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Phase 1: DETECT
|
|
224
|
+
Framework: React Native 0.73 (Expo SDK 50, managed workflow)
|
|
225
|
+
Platforms: iOS 16+, Android API 26+
|
|
226
|
+
Permissions: camera, notifications, location-when-in-use
|
|
227
|
+
Deep linking: expo-linking configured, no universal links
|
|
228
|
+
Push: expo-notifications with FCM
|
|
229
|
+
|
|
230
|
+
Phase 2: ANALYZE
|
|
231
|
+
[MOB-ERR-001] app.json
|
|
232
|
+
Missing NSCameraUsageDescription -- will cause App Store rejection
|
|
233
|
+
[MOB-WARN-001] src/screens/HomeScreen.tsx:15
|
|
234
|
+
Location permission requested on mount, not when map feature is used
|
|
235
|
+
[MOB-WARN-002] No notification channel configuration for Android
|
|
236
|
+
[MOB-INFO-001] expo-linking handles deep links but no deferred deep link support
|
|
237
|
+
|
|
238
|
+
Phase 3: ADVISE
|
|
239
|
+
Add to app.json plugins: ["expo-camera", { cameraPermission: "Take photos for your profile" }]
|
|
240
|
+
Move location request to MapScreen component
|
|
241
|
+
Add expo-notifications channel creation in App.tsx useEffect
|
|
242
|
+
Consider expo-linking with web fallback for deferred deep links
|
|
243
|
+
|
|
244
|
+
Phase 4: VALIDATE
|
|
245
|
+
Permissions complete after fix: YES
|
|
246
|
+
Deep link routing covers auth state: NO (needs auth check)
|
|
247
|
+
Store readiness: iOS PASS (after fix), Android NEEDS_ATTENTION (target SDK)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Example: Flutter App with Firebase
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
Phase 1: DETECT
|
|
254
|
+
Framework: Flutter 3.19, Dart 3.3
|
|
255
|
+
Platforms: iOS 14+, Android API 23+
|
|
256
|
+
Dependencies: firebase_messaging, firebase_dynamic_links, permission_handler
|
|
257
|
+
Permissions: camera, microphone, storage, notifications
|
|
258
|
+
|
|
259
|
+
Phase 2: ANALYZE
|
|
260
|
+
[MOB-ERR-001] android/app/build.gradle
|
|
261
|
+
targetSdkVersion 33 -- Play Store requires 34+ for new submissions
|
|
262
|
+
[MOB-ERR-002] lib/services/push_service.dart
|
|
263
|
+
onMessageOpenedApp handler missing -- tapped notifications from background do nothing
|
|
264
|
+
[MOB-WARN-001] lib/main.dart
|
|
265
|
+
All 4 permissions requested in initState -- should be contextual
|
|
266
|
+
[MOB-WARN-002] ios/Runner/Info.plist
|
|
267
|
+
NSMicrophoneUsageDescription: "Microphone access" -- too vague
|
|
268
|
+
|
|
269
|
+
Phase 3: ADVISE
|
|
270
|
+
Update targetSdkVersion to 34 and test for behavioral changes
|
|
271
|
+
Implement FirebaseMessaging.onMessageOpenedApp handler with navigation
|
|
272
|
+
Move permission requests to feature screens (camera on photo screen, mic on voice screen)
|
|
273
|
+
Update description: "Record voice messages to send to your team"
|
|
274
|
+
|
|
275
|
+
Phase 4: VALIDATE
|
|
276
|
+
Config consistency iOS vs Android: 3/4 permissions aligned (storage is Android-only, OK)
|
|
277
|
+
Push flow complete after fix: YES (foreground + background + terminated)
|
|
278
|
+
Store readiness after fixes: iOS PASS, Android PASS
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Example: Native iOS App (Swift) Store Submission Audit
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
Phase 1: DETECT
|
|
285
|
+
Framework: Native iOS (Swift 5.9, Xcode 15)
|
|
286
|
+
Deployment target: iOS 16.0
|
|
287
|
+
Capabilities: push notifications, associated domains, HealthKit
|
|
288
|
+
Permissions: health-share, health-update, notifications, location-always
|
|
289
|
+
|
|
290
|
+
Phase 2: ANALYZE
|
|
291
|
+
[MOB-ERR-001] Info.plist
|
|
292
|
+
Missing NSHealthShareUsageDescription for HealthKit read access
|
|
293
|
+
[MOB-ERR-002] Runner.entitlements
|
|
294
|
+
Associated domains list includes staging URL -- remove before production build
|
|
295
|
+
[MOB-WARN-001] AppDelegate.swift
|
|
296
|
+
Location-always permission requested without location-when-in-use fallback
|
|
297
|
+
Apple may reject: must request when-in-use first, then upgrade to always
|
|
298
|
+
[MOB-WARN-002] Privacy manifest (PrivacyInfo.xcprivacy) not present
|
|
299
|
+
Required for iOS 17+ submissions using required reason APIs
|
|
300
|
+
|
|
301
|
+
Phase 3: ADVISE
|
|
302
|
+
Add NSHealthShareUsageDescription: "View your daily step count and activity trends"
|
|
303
|
+
Create separate entitlements files for staging and production
|
|
304
|
+
Implement progressive location permission: when-in-use first, then always with explanation
|
|
305
|
+
Generate PrivacyInfo.xcprivacy with required reason API declarations
|
|
306
|
+
|
|
307
|
+
Phase 4: VALIDATE
|
|
308
|
+
All permission descriptions present after fix: YES
|
|
309
|
+
Entitlements clean for production: YES (after staging URL removal)
|
|
310
|
+
Privacy manifest complete: YES (after generation)
|
|
311
|
+
Store submission ready: PASS
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Gates
|
|
315
|
+
|
|
316
|
+
- **No missing permission usage descriptions.** Every permission requested in code must have a corresponding usage description in the platform manifest. Missing descriptions cause automatic App Store rejection on iOS and are a best practice requirement on Android.
|
|
317
|
+
- **No deep links to authenticated content without auth checks.** Every deep link handler that navigates to a protected screen must verify authentication state first. Unauthenticated users must be redirected to login with the deep link preserved for post-login navigation.
|
|
318
|
+
- **No publishing with staging configuration.** Staging URLs, debug API keys, or test server endpoints in production build configurations are always an error. Verify build variants isolate environment-specific values.
|
|
319
|
+
- **No requesting all permissions at app launch.** Permissions must be requested at the point of use with contextual explanation. Requesting all permissions on first launch results in lower grant rates and potential store rejection.
|
|
320
|
+
|
|
321
|
+
## Escalation
|
|
322
|
+
|
|
323
|
+
- **When platform-specific native code is required but the team uses a cross-platform framework:** Flag the bridging need: "This feature requires a custom native module for iOS (Swift) and Android (Kotlin). The React Native bridge needs to be implemented in `ios/` and `android/` directories. Consider if an existing library covers this use case."
|
|
324
|
+
- **When app store guidelines have recently changed:** If the analysis references a guideline that may be outdated, flag it: "Apple updated App Review Guidelines in [month]. The privacy manifest requirements may have changed -- verify against the current guidelines at developer.apple.com."
|
|
325
|
+
- **When deep linking requires server-side configuration:** If universal links or app links need server-side files, flag the cross-team dependency: "Universal Links require hosting `.well-known/apple-app-site-association` on your web domain. This needs coordination with the web/infrastructure team."
|
|
326
|
+
- **When push notification testing requires physical devices:** Flag the testing limitation: "Push notification delivery cannot be fully tested in simulators. APNs requires a physical device with a valid push token. Consider using a staging environment with real devices for end-to-end push testing."
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: harness-mobile-patterns
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Mobile platform lifecycle, permissions, deep linking, push notifications, and app store submission
|
|
4
|
+
cognitive_mode: advisory-guide
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
- on_new_feature
|
|
8
|
+
- on_pr
|
|
9
|
+
platforms:
|
|
10
|
+
- claude-code
|
|
11
|
+
- gemini-cli
|
|
12
|
+
tools:
|
|
13
|
+
- Bash
|
|
14
|
+
- Read
|
|
15
|
+
- Write
|
|
16
|
+
- Edit
|
|
17
|
+
- Glob
|
|
18
|
+
- Grep
|
|
19
|
+
- emit_interaction
|
|
20
|
+
cli:
|
|
21
|
+
command: harness skill run harness-mobile-patterns
|
|
22
|
+
args:
|
|
23
|
+
- name: path
|
|
24
|
+
description: Project root path
|
|
25
|
+
required: false
|
|
26
|
+
- name: platform
|
|
27
|
+
description: "Target platform: ios, android, react-native, flutter. Auto-detected when omitted."
|
|
28
|
+
required: false
|
|
29
|
+
- name: focus
|
|
30
|
+
description: "Audit focus: permissions, deep-links, push, lifecycle, store-submission, all. Defaults to all."
|
|
31
|
+
required: false
|
|
32
|
+
mcp:
|
|
33
|
+
tool: run_skill
|
|
34
|
+
input:
|
|
35
|
+
skill: harness-mobile-patterns
|
|
36
|
+
path: string
|
|
37
|
+
type: rigid
|
|
38
|
+
tier: 3
|
|
39
|
+
internal: false
|
|
40
|
+
keywords:
|
|
41
|
+
- mobile
|
|
42
|
+
- iOS
|
|
43
|
+
- Android
|
|
44
|
+
- React Native
|
|
45
|
+
- Flutter
|
|
46
|
+
- Swift
|
|
47
|
+
- Kotlin
|
|
48
|
+
- permissions
|
|
49
|
+
- deep link
|
|
50
|
+
- push notification
|
|
51
|
+
- app store
|
|
52
|
+
- Play Store
|
|
53
|
+
- App Store
|
|
54
|
+
- lifecycle
|
|
55
|
+
- universal link
|
|
56
|
+
stack_signals:
|
|
57
|
+
- "ios/"
|
|
58
|
+
- "android/"
|
|
59
|
+
- "App.tsx"
|
|
60
|
+
- "app.json"
|
|
61
|
+
- "pubspec.yaml"
|
|
62
|
+
- "Info.plist"
|
|
63
|
+
- "AndroidManifest.xml"
|
|
64
|
+
- "*.xcodeproj"
|
|
65
|
+
- "*.gradle"
|
|
66
|
+
phases:
|
|
67
|
+
- name: detect
|
|
68
|
+
description: Identify mobile platform, framework, native modules, and platform-specific configurations
|
|
69
|
+
required: true
|
|
70
|
+
- name: analyze
|
|
71
|
+
description: Evaluate permission handling, lifecycle management, deep linking, and push notification setup
|
|
72
|
+
required: true
|
|
73
|
+
- name: advise
|
|
74
|
+
description: Recommend platform-specific best practices, missing configurations, and store compliance fixes
|
|
75
|
+
required: true
|
|
76
|
+
- name: validate
|
|
77
|
+
description: Verify configurations are complete, permissions are justified, and store guidelines are met
|
|
78
|
+
required: true
|
|
79
|
+
state:
|
|
80
|
+
persistent: false
|
|
81
|
+
files: []
|
|
82
|
+
depends_on: []
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Harness Mutation Test
|
|
2
|
+
|
|
3
|
+
> Test quality validation through mutation testing. Introduces deliberate code mutations to verify that the test suite catches real bugs, exposing weak assertions, missing edge cases, and dead test code.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Evaluating test suite quality after reaching a coverage threshold (e.g., 80% line coverage)
|
|
8
|
+
- Validating that tests for critical business logic actually catch bugs, not just execute code
|
|
9
|
+
- Identifying which parts of the codebase have weak or superficial test coverage
|
|
10
|
+
- NOT when test coverage is below 60% (write more tests first with harness-tdd)
|
|
11
|
+
- NOT when optimizing test execution speed (mutation testing is inherently slow)
|
|
12
|
+
- NOT when the codebase has no existing tests (establish a test foundation first)
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
### Phase 1: CONFIGURE -- Set Up Mutation Testing Framework
|
|
17
|
+
|
|
18
|
+
1. **Detect the project's language and test framework.** Mutation testing tools are language-specific:
|
|
19
|
+
- **TypeScript/JavaScript:** Stryker Mutator with Vitest, Jest, or Mocha runner
|
|
20
|
+
- **Python:** mutmut or cosmic-ray with pytest
|
|
21
|
+
- **Java/Kotlin:** PIT (pitest) with JUnit or TestNG
|
|
22
|
+
- **C#:** Stryker.NET with NUnit, xUnit, or MSTest
|
|
23
|
+
- **Rust:** cargo-mutants
|
|
24
|
+
|
|
25
|
+
2. **Install and configure the mutation framework.** Generate the configuration file:
|
|
26
|
+
- Target source directories (exclude generated code, vendor, node_modules)
|
|
27
|
+
- Test command and timeout multiplier (mutations may cause infinite loops)
|
|
28
|
+
- Mutant operators to enable (arithmetic, conditional, string, logical)
|
|
29
|
+
- Reporters (HTML for local review, JSON for CI integration)
|
|
30
|
+
|
|
31
|
+
3. **Define the scope.** Mutation testing is expensive. Scope it:
|
|
32
|
+
- **Targeted run:** specific files or directories with high business value
|
|
33
|
+
- **Incremental run:** only files changed since the last mutation run
|
|
34
|
+
- **Full run:** entire codebase (reserve for milestones or nightly CI)
|
|
35
|
+
|
|
36
|
+
4. **Set the mutation score threshold.** Define the minimum acceptable score:
|
|
37
|
+
- 80% for business-critical modules (payment, auth, data processing)
|
|
38
|
+
- 60% for general application code
|
|
39
|
+
- No threshold for infrastructure/glue code (routers, middleware wiring)
|
|
40
|
+
|
|
41
|
+
5. **Verify the test suite passes before mutating.** Run the full test suite. All tests must pass. Mutation testing against a failing suite produces meaningless results.
|
|
42
|
+
|
|
43
|
+
### Phase 2: GENERATE -- Create Mutants
|
|
44
|
+
|
|
45
|
+
1. **Run mutant generation in dry-run mode.** List the mutations that will be applied without executing tests. Review:
|
|
46
|
+
- Total mutant count (hundreds to thousands depending on codebase size)
|
|
47
|
+
- Mutant distribution across files
|
|
48
|
+
- Types of mutations generated (arithmetic, conditional boundary, return value, etc.)
|
|
49
|
+
|
|
50
|
+
2. **Review the mutant operators.** Ensure the configured operators are relevant:
|
|
51
|
+
- **Arithmetic:** `+` to `-`, `*` to `/` -- tests mathematical correctness
|
|
52
|
+
- **Conditional boundary:** `<` to `<=`, `>` to `>=` -- tests off-by-one handling
|
|
53
|
+
- **Negate conditional:** `==` to `!=`, `true` to `false` -- tests branch coverage
|
|
54
|
+
- **Return value:** return empty string, zero, null, empty array -- tests output validation
|
|
55
|
+
- **String mutation:** `"hello"` to `""` -- tests string handling
|
|
56
|
+
- **Remove call:** delete a method call entirely -- tests that side effects are verified
|
|
57
|
+
|
|
58
|
+
3. **Estimate execution time.** Calculate:
|
|
59
|
+
- Number of mutants times average test suite duration divided by parallelism factor
|
|
60
|
+
- If estimated time exceeds 30 minutes, reduce scope or increase parallelism
|
|
61
|
+
|
|
62
|
+
4. **Filter out equivalent mutants (where possible).** Some mutations produce functionally identical code (e.g., changing the order of commutative operations). Configure the framework to skip known equivalent patterns to reduce noise.
|
|
63
|
+
|
|
64
|
+
### Phase 3: EXECUTE -- Run Tests Against Mutants
|
|
65
|
+
|
|
66
|
+
1. **Execute the mutation test run.** Start the framework with the configured scope:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
npx stryker run --concurrency 4
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
or
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
pitest:mutationCoverage
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
2. **Monitor progress.** Track:
|
|
79
|
+
- Mutants tested vs. total
|
|
80
|
+
- Kill rate as it progresses
|
|
81
|
+
- Timeouts (mutants that cause infinite loops -- these count as killed)
|
|
82
|
+
- Errors (mutants that cause compilation failures -- these are stillborn, not counted)
|
|
83
|
+
|
|
84
|
+
3. **Handle long-running mutations.** If a single mutant takes longer than 3x the normal test timeout:
|
|
85
|
+
- The mutation likely introduced an infinite loop
|
|
86
|
+
- The framework should kill it automatically (timeout = killed)
|
|
87
|
+
- If the framework hangs, check the timeout multiplier configuration
|
|
88
|
+
|
|
89
|
+
4. **Collect results.** After completion, the framework produces:
|
|
90
|
+
- Mutation score: (killed + timeout) / (total - stillborn - ignored)
|
|
91
|
+
- Per-file mutation scores
|
|
92
|
+
- List of survived mutants with their locations and mutation descriptions
|
|
93
|
+
|
|
94
|
+
### Phase 4: ANALYZE -- Interpret Results and Improve Tests
|
|
95
|
+
|
|
96
|
+
1. **Review the overall mutation score.** Compare against the threshold:
|
|
97
|
+
- Above threshold: test quality is acceptable. Review survived mutants for targeted improvements.
|
|
98
|
+
- Below threshold: significant test gaps exist. Prioritize fixes by file criticality.
|
|
99
|
+
|
|
100
|
+
2. **Examine survived mutants.** For each survived mutant, determine why the test suite did not catch it:
|
|
101
|
+
- **Missing assertion:** the test executes the code but does not assert on the affected output. Fix: add a specific assertion.
|
|
102
|
+
- **Missing test case:** no test covers the mutated branch. Fix: write a new test for that path.
|
|
103
|
+
- **Weak assertion:** the test asserts but too loosely (e.g., `toBeTruthy()` instead of `toBe(42)`). Fix: strengthen the assertion.
|
|
104
|
+
- **Equivalent mutant:** the mutation does not change observable behavior. Mark as ignored.
|
|
105
|
+
|
|
106
|
+
3. **Prioritize improvements by business impact.** Focus on survived mutants in:
|
|
107
|
+
- Authentication and authorization logic
|
|
108
|
+
- Payment and billing calculations
|
|
109
|
+
- Data validation and sanitization
|
|
110
|
+
- Core domain algorithms
|
|
111
|
+
|
|
112
|
+
4. **Write targeted tests for the highest-priority survived mutants.** For each:
|
|
113
|
+
- Write a test that fails against the mutated code but passes against the original
|
|
114
|
+
- Verify the test is meaningful (not just mutation-hunting -- it should test real behavior)
|
|
115
|
+
- Run the mutation test again on the affected file to confirm the mutant is now killed
|
|
116
|
+
|
|
117
|
+
5. **Generate an improvement report.** Summarize:
|
|
118
|
+
- Starting mutation score vs. ending mutation score
|
|
119
|
+
- Number of survived mutants addressed
|
|
120
|
+
- Tests added or strengthened
|
|
121
|
+
- Remaining gaps with recommendations
|
|
122
|
+
|
|
123
|
+
6. **Run `harness validate`.** Confirm the project passes all harness checks after test improvements.
|
|
124
|
+
|
|
125
|
+
### Graph Refresh
|
|
126
|
+
|
|
127
|
+
If a knowledge graph exists at `.harness/graph/`, refresh it after code changes to keep graph queries accurate:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
harness scan [path]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Harness Integration
|
|
134
|
+
|
|
135
|
+
- **`harness validate`** -- Run in ANALYZE phase after tests are improved. Confirms project health with strengthened tests.
|
|
136
|
+
- **`harness check-deps`** -- Run after CONFIGURE phase to verify mutation testing framework is in devDependencies.
|
|
137
|
+
- **`emit_interaction`** -- Used to present mutation score results and survived mutant analysis to the human for prioritization decisions.
|
|
138
|
+
- **Grep** -- Used in ANALYZE phase to find weak assertions (`toBeTruthy`, `toBeDefined`, `!= null`) and missing assertion patterns.
|
|
139
|
+
- **Glob** -- Used to identify test files corresponding to source files with survived mutants.
|
|
140
|
+
|
|
141
|
+
## Success Criteria
|
|
142
|
+
|
|
143
|
+
- Mutation score meets or exceeds the defined threshold for targeted modules
|
|
144
|
+
- Every survived mutant in critical business logic has been addressed or explicitly justified
|
|
145
|
+
- New tests written for survived mutants test real behavior, not just mutation-specific code paths
|
|
146
|
+
- Weak assertions (`toBeTruthy`, `toBeDefined`, `expect(result)` without matcher) are replaced with specific assertions
|
|
147
|
+
- The mutation test configuration is committed and can run in CI
|
|
148
|
+
- `harness validate` passes after test improvements
|
|
149
|
+
|
|
150
|
+
## Examples
|
|
151
|
+
|
|
152
|
+
### Example: Stryker Mutation Testing for a TypeScript Billing Module
|
|
153
|
+
|
|
154
|
+
**CONFIGURE -- Stryker configuration:**
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// stryker.config.mjs
|
|
158
|
+
/** @type {import('@stryker-mutator/api/core').PartialStrykerOptions} */
|
|
159
|
+
export default {
|
|
160
|
+
mutate: ['src/billing/**/*.ts', '!src/billing/**/*.test.ts'],
|
|
161
|
+
testRunner: 'vitest',
|
|
162
|
+
reporters: ['html', 'clear-text', 'progress'],
|
|
163
|
+
coverageAnalysis: 'perTest',
|
|
164
|
+
timeoutMS: 30000,
|
|
165
|
+
concurrency: 4,
|
|
166
|
+
thresholds: {
|
|
167
|
+
high: 90,
|
|
168
|
+
low: 80,
|
|
169
|
+
break: 75,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**ANALYZE -- Survived mutant investigation:**
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Mutant #47: src/billing/calculate-discount.ts:23
|
|
178
|
+
Original: if (quantity >= 10) { discount = 0.15; }
|
|
179
|
+
Mutation: if (quantity > 10) { discount = 0.15; }
|
|
180
|
+
Status: SURVIVED
|
|
181
|
+
|
|
182
|
+
Analysis: No test checks the boundary condition where quantity is exactly 10.
|
|
183
|
+
The existing test uses quantity=20 (well above threshold) and quantity=5 (below).
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Fix -- Add boundary test:**
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// src/billing/calculate-discount.test.ts
|
|
190
|
+
it('applies 15% discount when quantity is exactly 10', () => {
|
|
191
|
+
const result = calculateDiscount({ quantity: 10, unitPrice: 100 });
|
|
192
|
+
expect(result.discount).toBe(0.15);
|
|
193
|
+
expect(result.total).toBe(850);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('does not apply discount when quantity is 9', () => {
|
|
197
|
+
const result = calculateDiscount({ quantity: 9, unitPrice: 100 });
|
|
198
|
+
expect(result.discount).toBe(0);
|
|
199
|
+
expect(result.total).toBe(900);
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Example: PIT Mutation Testing for a Java Service
|
|
204
|
+
|
|
205
|
+
**CONFIGURE -- Maven PIT plugin:**
|
|
206
|
+
|
|
207
|
+
```xml
|
|
208
|
+
<!-- pom.xml -->
|
|
209
|
+
<plugin>
|
|
210
|
+
<groupId>org.pitest</groupId>
|
|
211
|
+
<artifactId>pitest-maven</artifactId>
|
|
212
|
+
<version>1.15.3</version>
|
|
213
|
+
<configuration>
|
|
214
|
+
<targetClasses>
|
|
215
|
+
<param>com.example.orders.*</param>
|
|
216
|
+
</targetClasses>
|
|
217
|
+
<targetTests>
|
|
218
|
+
<param>com.example.orders.*Test</param>
|
|
219
|
+
</targetTests>
|
|
220
|
+
<mutators>
|
|
221
|
+
<mutator>CONDITIONALS_BOUNDARY</mutator>
|
|
222
|
+
<mutator>NEGATE_CONDITIONALS</mutator>
|
|
223
|
+
<mutator>RETURN_VALS</mutator>
|
|
224
|
+
<mutator>MATH</mutator>
|
|
225
|
+
</mutators>
|
|
226
|
+
<mutationThreshold>80</mutationThreshold>
|
|
227
|
+
<timestampedReports>false</timestampedReports>
|
|
228
|
+
</configuration>
|
|
229
|
+
</plugin>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**EXECUTE:**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
mvn org.pitest:pitest-maven:mutationCoverage
|
|
236
|
+
# Report generated at target/pit-reports/index.html
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Gates
|
|
240
|
+
|
|
241
|
+
- **No mutation testing against a failing test suite.** All tests must pass before mutants are generated. Running mutations against broken tests produces garbage results. Fix the tests first.
|
|
242
|
+
- **Survived mutants in critical modules must be addressed.** If a survived mutant is in authentication, billing, or data validation logic, it cannot be ignored. Write a test or justify why the mutation is equivalent.
|
|
243
|
+
- **No gaming the mutation score.** Writing tests that only target survived mutants without testing real behavior inflates the score without improving quality. Every new test must test a meaningful behavior, not just kill a specific mutant.
|
|
244
|
+
- **Mutation score regression blocks merge.** If the mutation score drops below the configured threshold after a code change, the change must include tests that restore the score before merging.
|
|
245
|
+
|
|
246
|
+
## Escalation
|
|
247
|
+
|
|
248
|
+
- **When mutation testing takes too long (> 1 hour for targeted run):** Reduce scope to changed files only. Use incremental mutation testing if the framework supports it. For full runs, schedule as a nightly CI job rather than blocking PRs.
|
|
249
|
+
- **When a high number of equivalent mutants skew the score:** Review mutant operators. Disable operators that produce mostly equivalent mutants for the codebase (e.g., string mutations in a codebase with few string operations). Document disabled operators and the rationale.
|
|
250
|
+
- **When the team disputes whether a survived mutant matters:** Evaluate: would a real bug in that code path cause user-visible harm? If yes, write the test. If no, document it as an accepted risk with a code comment explaining why.
|
|
251
|
+
- **When mutation testing reveals architectural issues (untestable code):** This is a design signal, not a testing problem. Escalate to refactoring -- the code needs dependency injection, interface extraction, or seam creation before meaningful tests can be written.
|