@harness-engineering/cli 1.13.0 → 1.14.0
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.md +39 -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.md +44 -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.md +44 -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.md +39 -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.md +3 -3
- 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.md +35 -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.md +11 -3
- 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.md +39 -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.md +44 -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.md +44 -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.md +39 -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.md +3 -3
- 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.md +35 -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.md +11 -3
- 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-YTYQDA3P.js +8 -0
- package/dist/{architecture-ESOOE26S.js → architecture-JQZYM4US.js} +4 -4
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +31 -30
- package/dist/{check-phase-gate-S2MZKLFQ.js → check-phase-gate-L3RADYWO.js} +4 -3
- package/dist/{chunk-WPPDRIJL.js → chunk-3C2MLBPJ.js} +4 -4
- package/dist/chunk-6KTUUFRN.js +217 -0
- package/dist/{chunk-MI5XJQDY.js → chunk-7IP4JIFL.js} +24 -10
- package/dist/{chunk-C2ERUR3L.js → chunk-7MJAPE3Z.js} +165 -49
- package/dist/{chunk-KELT6K6M.js → chunk-ABQHQ6I5.js} +1861 -1418
- package/dist/{chunk-L2KLU56K.js → chunk-AOZRDOIP.js} +2 -2
- package/dist/{chunk-QPEH2QPG.js → chunk-DBSOCI3G.js} +53 -54
- package/dist/{chunk-MHBMTPW7.js → chunk-ERS5EVUZ.js} +9 -0
- package/dist/{chunk-JSTQ3AWB.js → chunk-FIAPHX37.js} +1 -1
- package/dist/{chunk-2YPZKGAG.js → chunk-FTMXDOR6.js} +1 -1
- package/dist/{chunk-72GHBOL2.js → chunk-GZKSBLQL.js} +1 -1
- package/dist/{chunk-K6XAPGML.js → chunk-H7Y5CKTM.js} +1 -1
- package/dist/{chunk-HD4IBGLA.js → chunk-N5G5QMS3.js} +24 -1
- package/dist/{chunk-LD3DKUK5.js → chunk-NLVUVUGD.js} +1 -1
- package/dist/{chunk-3KOLLWWE.js → chunk-O5OJVPL6.js} +26 -211
- package/dist/{chunk-NKDM3FMH.js → chunk-OD3S2NHN.js} +1 -1
- package/dist/{chunk-5VY23YK3.js → chunk-OSXBPAMK.js} +2 -2
- package/dist/{chunk-MACVXDZK.js → chunk-OXLLOSSR.js} +45 -47
- package/dist/{chunk-GNGELAXY.js → chunk-RCWZBSK5.js} +2 -2
- package/dist/{chunk-PSNN4LWX.js → chunk-S2FXOWOR.js} +3 -3
- package/dist/{chunk-VUCPTQ6G.js → chunk-SD3SQOZ2.js} +1 -1
- package/dist/{chunk-7PZWR4LI.js → chunk-TPOTOBR7.js} +9 -9
- package/dist/{chunk-RZSUJBZZ.js → chunk-XKECDXJS.js} +452 -353
- package/dist/{chunk-VRFZWGMS.js → chunk-XYLGHKG6.js} +5 -1
- package/dist/{chunk-6N4R6FVX.js → chunk-YBJ262QL.js} +1 -1
- package/dist/{chunk-2VU4MFM3.js → chunk-YPYGXRDR.js} +7 -7
- package/dist/{chunk-Q6AB7W5Z.js → chunk-YQ6KC6TE.js} +1 -1
- package/dist/{chunk-7KQSUZVG.js → chunk-YZD2MRNQ.js} +1528 -1010
- package/dist/ci-workflow-EQZFVX3P.js +8 -0
- package/dist/{create-skill-WPXHSLX2.js → create-skill-XSWHMSM5.js} +2 -2
- package/dist/{dist-M6BQODWC.js → dist-B26DFXMP.js} +573 -480
- package/dist/{dist-L7LAAQAS.js → dist-DZ63LLUD.js} +1 -1
- package/dist/{dist-WF4C7A4A.js → dist-HWXF2C3R.js} +18 -2
- package/dist/{dist-D4RYGUZE.js → dist-USY2C5JL.js} +3 -1
- package/dist/{docs-BPYCN2DR.js → docs-7ECGYMAV.js} +5 -3
- package/dist/engine-EG4EH4IX.js +8 -0
- package/dist/{entropy-4VDVV5CR.js → entropy-5USWKLVS.js} +3 -3
- package/dist/{feedback-63QB5RCA.js → feedback-UTBXZZHF.js} +1 -1
- package/dist/{generate-agent-definitions-QABOJG56.js → generate-agent-definitions-3PM5EU7V.js} +5 -5
- package/dist/{glob-helper-5OHBUQAI.js → glob-helper-R5FXNUPS.js} +1 -1
- package/dist/{graph-loader-KO4GJ5N2.js → graph-loader-2M2HXDQI.js} +1 -1
- package/dist/index.d.ts +183 -17
- package/dist/index.js +32 -30
- package/dist/loader-ZPALXIVR.js +10 -0
- package/dist/mcp-362EZHF4.js +35 -0
- package/dist/{performance-26BH47O4.js → performance-OQAFMJUD.js} +3 -3
- package/dist/{review-pipeline-GHR3WFBI.js → review-pipeline-C4GCFVGP.js} +1 -1
- package/dist/runtime-7YLVK453.js +9 -0
- package/dist/{security-UQFUZXEN.js → security-PZOX7AQS.js} +1 -1
- package/dist/skill-executor-XZLYZYAK.js +8 -0
- package/dist/templates/axum/Cargo.toml.hbs +8 -0
- package/dist/templates/axum/src/main.rs +12 -0
- package/dist/templates/axum/template.json +16 -0
- package/dist/templates/django/manage.py.hbs +19 -0
- package/dist/templates/django/requirements.txt.hbs +1 -0
- package/dist/templates/django/src/settings.py.hbs +44 -0
- package/dist/templates/django/src/urls.py +6 -0
- package/dist/templates/django/src/wsgi.py.hbs +9 -0
- package/dist/templates/django/template.json +21 -0
- package/dist/templates/express/package.json.hbs +15 -0
- package/dist/templates/express/src/app.ts +12 -0
- package/dist/templates/express/src/lib/.gitkeep +0 -0
- package/dist/templates/express/template.json +16 -0
- package/dist/templates/fastapi/requirements.txt.hbs +2 -0
- package/dist/templates/fastapi/src/main.py +8 -0
- package/dist/templates/fastapi/template.json +20 -0
- package/dist/templates/gin/go.mod.hbs +5 -0
- package/dist/templates/gin/main.go +15 -0
- package/dist/templates/gin/template.json +19 -0
- package/dist/templates/go-base/.golangci.yml +16 -0
- package/dist/templates/go-base/AGENTS.md.hbs +35 -0
- package/dist/templates/go-base/go.mod.hbs +3 -0
- package/dist/templates/go-base/harness.config.json.hbs +17 -0
- package/dist/templates/go-base/main.go +7 -0
- package/dist/templates/go-base/template.json +14 -0
- package/dist/templates/java-base/AGENTS.md.hbs +35 -0
- package/dist/templates/java-base/checkstyle.xml +20 -0
- package/dist/templates/java-base/harness.config.json.hbs +16 -0
- package/dist/templates/java-base/pom.xml.hbs +39 -0
- package/dist/templates/java-base/src/main/java/App.java.hbs +5 -0
- package/dist/templates/java-base/template.json +13 -0
- package/dist/templates/nestjs/nest-cli.json +5 -0
- package/dist/templates/nestjs/package.json.hbs +18 -0
- package/dist/templates/nestjs/src/app.module.ts +8 -0
- package/dist/templates/nestjs/src/lib/.gitkeep +0 -0
- package/dist/templates/nestjs/src/main.ts +11 -0
- package/dist/templates/nestjs/template.json +16 -0
- package/dist/templates/nextjs/template.json +15 -1
- package/dist/templates/python-base/.python-version +1 -0
- package/dist/templates/python-base/AGENTS.md.hbs +32 -0
- package/dist/templates/python-base/harness.config.json.hbs +16 -0
- package/dist/templates/python-base/pyproject.toml.hbs +18 -0
- package/dist/templates/python-base/ruff.toml +5 -0
- package/dist/templates/python-base/src/__init__.py +0 -0
- package/dist/templates/python-base/template.json +13 -0
- package/dist/templates/react-vite/index.html +12 -0
- package/dist/templates/react-vite/package.json.hbs +18 -0
- package/dist/templates/react-vite/src/App.tsx +7 -0
- package/dist/templates/react-vite/src/lib/.gitkeep +0 -0
- package/dist/templates/react-vite/src/main.tsx +9 -0
- package/dist/templates/react-vite/template.json +19 -0
- package/dist/templates/react-vite/vite.config.ts +6 -0
- package/dist/templates/rust-base/AGENTS.md.hbs +35 -0
- package/dist/templates/rust-base/Cargo.toml.hbs +6 -0
- package/dist/templates/rust-base/clippy.toml +2 -0
- package/dist/templates/rust-base/harness.config.json.hbs +17 -0
- package/dist/templates/rust-base/src/main.rs +3 -0
- package/dist/templates/rust-base/template.json +14 -0
- package/dist/templates/spring-boot/pom.xml.hbs +50 -0
- package/dist/templates/spring-boot/src/main/java/Application.java.hbs +19 -0
- package/dist/templates/spring-boot/template.json +15 -0
- package/dist/templates/vue/index.html +12 -0
- package/dist/templates/vue/package.json.hbs +16 -0
- package/dist/templates/vue/src/App.vue +7 -0
- package/dist/templates/vue/src/lib/.gitkeep +0 -0
- package/dist/templates/vue/src/main.ts +4 -0
- package/dist/templates/vue/template.json +19 -0
- package/dist/templates/vue/vite.config.ts +6 -0
- package/dist/{validate-N7QJOKFZ.js → validate-FD3Z6VJD.js} +4 -4
- package/dist/validate-cross-check-WNJM6H2D.js +8 -0
- package/package.json +6 -6
- package/dist/agents-md-P2RHSUV7.js +0 -8
- package/dist/ci-workflow-4NYBUG6R.js +0 -8
- package/dist/engine-LXLIWQQ3.js +0 -8
- package/dist/loader-Z2IT7QX3.js +0 -10
- package/dist/mcp-KQHEL5IF.js +0 -34
- package/dist/runtime-PDWD7UIK.js +0 -9
- package/dist/skill-executor-RG45LUO5.js +0 -8
- package/dist/validate-cross-check-EDQ5QGTM.js +0 -8
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: harness-auth
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: OAuth2, JWT, RBAC/ABAC, session management, and MFA patterns
|
|
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-auth
|
|
22
|
+
args:
|
|
23
|
+
- name: path
|
|
24
|
+
description: Project root path
|
|
25
|
+
required: false
|
|
26
|
+
- name: focus
|
|
27
|
+
description: "Auth area to focus on: authn, authz, session, mfa, or all. Defaults to all."
|
|
28
|
+
required: false
|
|
29
|
+
- name: framework
|
|
30
|
+
description: "Auth framework in use: passport, next-auth, auth0, firebase-auth, or custom. Auto-detected when omitted."
|
|
31
|
+
required: false
|
|
32
|
+
mcp:
|
|
33
|
+
tool: run_skill
|
|
34
|
+
input:
|
|
35
|
+
skill: harness-auth
|
|
36
|
+
path: string
|
|
37
|
+
type: rigid
|
|
38
|
+
tier: 3
|
|
39
|
+
internal: false
|
|
40
|
+
keywords:
|
|
41
|
+
- auth
|
|
42
|
+
- authentication
|
|
43
|
+
- authorization
|
|
44
|
+
- OAuth2
|
|
45
|
+
- JWT
|
|
46
|
+
- RBAC
|
|
47
|
+
- ABAC
|
|
48
|
+
- session
|
|
49
|
+
- MFA
|
|
50
|
+
- OIDC
|
|
51
|
+
- SSO
|
|
52
|
+
- SAML
|
|
53
|
+
- passport
|
|
54
|
+
- token
|
|
55
|
+
- refresh token
|
|
56
|
+
- PKCE
|
|
57
|
+
stack_signals:
|
|
58
|
+
- "src/**/auth/**"
|
|
59
|
+
- "src/**/middleware/auth*"
|
|
60
|
+
- "src/**/*passport*"
|
|
61
|
+
- "src/**/*jwt*"
|
|
62
|
+
- "src/**/*session*"
|
|
63
|
+
- "src/**/guards/**"
|
|
64
|
+
- "src/**/policies/**"
|
|
65
|
+
phases:
|
|
66
|
+
- name: detect
|
|
67
|
+
description: Identify authentication and authorization mechanisms, providers, and token flows
|
|
68
|
+
required: true
|
|
69
|
+
- name: analyze
|
|
70
|
+
description: Evaluate security posture, token lifecycle, permission models, and session handling
|
|
71
|
+
required: true
|
|
72
|
+
- name: design
|
|
73
|
+
description: Recommend improvements for auth flows, RBAC/ABAC models, and MFA integration
|
|
74
|
+
required: true
|
|
75
|
+
- name: validate
|
|
76
|
+
description: Verify auth implementation against OWASP guidelines and common vulnerability patterns
|
|
77
|
+
required: true
|
|
78
|
+
state:
|
|
79
|
+
persistent: false
|
|
80
|
+
files: []
|
|
81
|
+
depends_on: []
|
|
@@ -259,6 +259,45 @@ For each proposed approach, evaluate from each perspective:
|
|
|
259
259
|
|
|
260
260
|
Converge on a recommendation that addresses all concerns before presenting the design.
|
|
261
261
|
|
|
262
|
+
## Session State
|
|
263
|
+
|
|
264
|
+
This skill reads and writes to the following session sections via `manage_state`:
|
|
265
|
+
|
|
266
|
+
| Section | Read | Write | Purpose |
|
|
267
|
+
| ------------- | ---- | ----- | ----------------------------------------------------------------- |
|
|
268
|
+
| terminology | yes | yes | Captures domain terms discovered during brainstorming |
|
|
269
|
+
| decisions | no | yes | Records design decisions made during exploration |
|
|
270
|
+
| constraints | yes | no | Reads constraints to scope brainstorming |
|
|
271
|
+
| risks | no | yes | Captures risks identified during brainstorming |
|
|
272
|
+
| openQuestions | yes | yes | Adds new questions, resolves answered ones |
|
|
273
|
+
| evidence | no | yes | Cites sources for design recommendations and prior art references |
|
|
274
|
+
|
|
275
|
+
**When to write:** After each phase transition (EXPLORE -> EVALUATE -> PRIORITIZE -> VALIDATE), append relevant entries to the appropriate sections. This ensures downstream skills (planning, execution) inherit accumulated context without re-discovery.
|
|
276
|
+
|
|
277
|
+
**When to read:** At the start of Phase 1 (EXPLORE), read `terminology` and `constraints` from the session to inherit context from prior skills or previous brainstorming sessions on the same feature.
|
|
278
|
+
|
|
279
|
+
## Evidence Requirements
|
|
280
|
+
|
|
281
|
+
When this skill makes claims about existing code behavior, architecture patterns, or technical tradeoffs, it MUST cite evidence using one of:
|
|
282
|
+
|
|
283
|
+
1. **File reference:** `file:line` format (e.g., `src/services/auth.ts:42` -- "existing JWT middleware handles token refresh")
|
|
284
|
+
2. **Prior art reference:** `file` format with description (e.g., `src/utils/email.ts` -- "email utility already exists, can be reused for notifications")
|
|
285
|
+
3. **Documentation reference:** `docs/path` format (e.g., `docs/changes/user-auth/proposal.md` -- "prior spec established OAuth2 as the auth standard")
|
|
286
|
+
4. **Session evidence:** Write to the `evidence` session section:
|
|
287
|
+
```json
|
|
288
|
+
manage_state({
|
|
289
|
+
action: "append_entry",
|
|
290
|
+
session: "<current-session>",
|
|
291
|
+
section: "evidence",
|
|
292
|
+
authorSkill: "harness-brainstorming",
|
|
293
|
+
content: "src/services/auth.ts:42 -- existing JWT middleware supports refresh tokens"
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**When to cite:** During Phase 1 (EXPLORE) when referencing existing code or patterns. During Phase 3 (PRIORITIZE) when justifying tradeoffs with concrete code references. During Phase 4 (VALIDATE) when spec references existing implementation details.
|
|
298
|
+
|
|
299
|
+
**Uncited claims:** Technical assertions without citations MUST be prefixed with `[UNVERIFIED]`. Example: `[UNVERIFIED] The current auth middleware does not support refresh tokens`. Uncited claims are flagged during review (Wave 2.2).
|
|
300
|
+
|
|
262
301
|
## Harness Integration
|
|
263
302
|
|
|
264
303
|
- **`harness validate`** — Run after writing the spec to `docs/`. Verifies project health and that the new spec file is properly placed.
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Harness Caching
|
|
2
|
+
|
|
3
|
+
> Advisory guide for cache strategies, invalidation patterns, and distributed caching. Detects existing cache usage, analyzes access patterns, designs cache layers with proper invalidation, and validates consistency guarantees.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- When adding a caching layer to an existing application (Redis, Memcached, in-memory)
|
|
8
|
+
- When designing cache invalidation strategies for data consistency
|
|
9
|
+
- When troubleshooting cache-related bugs (stale data, thundering herd, cache stampede)
|
|
10
|
+
- When evaluating HTTP caching headers (Cache-Control, ETag, Vary)
|
|
11
|
+
- When designing a distributed cache for a multi-instance deployment
|
|
12
|
+
- When reviewing CDN caching configuration for static or dynamic content
|
|
13
|
+
- NOT for database query optimization (use harness-database for indexing and query patterns)
|
|
14
|
+
- NOT for message queue pub/sub with Redis (use harness-event-driven for async messaging)
|
|
15
|
+
- NOT for session storage design (use harness-auth for session management patterns)
|
|
16
|
+
- NOT for in-memory data structures or algorithms (this skill focuses on caching as an architectural pattern)
|
|
17
|
+
|
|
18
|
+
## Process
|
|
19
|
+
|
|
20
|
+
### Phase 1: DETECT -- Identify Existing Cache Usage and Backends
|
|
21
|
+
|
|
22
|
+
1. **Detect cache backends.** Scan for stack signals: `docker-compose.*redis*` or `ioredis`/`redis` imports for Redis, `docker-compose.*memcached*` or `memcached` imports for Memcached, `node-cache` or `lru-cache` imports for in-memory caches. Check for CDN configuration in `vercel.json`, `netlify.toml`, `cloudfront`, or nginx config files.
|
|
23
|
+
|
|
24
|
+
2. **Map existing cache usage.** Scan for cache operations: `cache.get(`, `cache.set(`, `redis.get(`, `redis.set(`, `redis.hget(`, `.setex(`, `.getex(`, and memoization decorators (`@Cacheable`, `@CacheEvict`). For each cache call, record: the cache key pattern, the TTL, the data being cached, and the source module.
|
|
25
|
+
|
|
26
|
+
3. **Identify access patterns.** For each cached resource, classify the access pattern: read-heavy (high read:write ratio, good cache candidate), write-heavy (frequent updates, invalidation-critical), time-sensitive (TTL must be short), or session-scoped (per-user data). Count the approximate read:write ratio from code analysis.
|
|
27
|
+
|
|
28
|
+
4. **Detect cache invalidation logic.** Scan for cache deletion or expiration calls: `cache.del(`, `redis.del(`, `cache.invalidate(`, `redis.expire(`, `cache.clear(`. Map each invalidation to the corresponding write operation. Flag cached data that is written but never explicitly invalidated.
|
|
29
|
+
|
|
30
|
+
5. **Check for existing cache problems.** Look for common anti-patterns: unbounded caches (no maxSize or TTL), cache keys built from user input without sanitization, cache-aside with no error handling on cache miss, and string-concatenated keys without namespace prefixes.
|
|
31
|
+
|
|
32
|
+
### Phase 2: ANALYZE -- Evaluate Cache Effectiveness and Risks
|
|
33
|
+
|
|
34
|
+
1. **Assess TTL appropriateness.** For each cached resource, evaluate whether the TTL matches the data's volatility. WHERE a frequently-updated resource has a TTL greater than 60 seconds, THEN flag potential staleness. WHERE a rarely-updated resource has a TTL less than 60 seconds, THEN flag unnecessary cache churn.
|
|
35
|
+
|
|
36
|
+
2. **Check for thundering herd risk.** WHERE a popular cache key expires and multiple concurrent requests trigger simultaneous cache rebuilds, THEN flag the thundering herd. Identify keys with high read frequency and non-trivial rebuild cost (database query, external API call).
|
|
37
|
+
|
|
38
|
+
3. **Evaluate cache key design.** Check for: overly broad keys that cache too much data (reducing hit rate), overly specific keys that create too many entries (memory pressure), missing namespace prefixes (key collision risk across features), and keys that include volatile data (timestamp, random ID) making them un-cacheable.
|
|
39
|
+
|
|
40
|
+
4. **Assess memory pressure.** WHERE an in-memory cache has no `maxSize` configuration, THEN flag unbounded memory growth. WHERE Redis is used without a `maxmemory` policy, THEN flag the risk of Redis running out of memory and evicting keys unpredictably.
|
|
41
|
+
|
|
42
|
+
5. **Check cache-database consistency.** Trace each write path that modifies cached data. WHERE the database write succeeds but cache invalidation could fail (separate operations, no transaction), THEN flag the consistency risk. Classify as eventual consistency (acceptable) or strong consistency (requires synchronous invalidation).
|
|
43
|
+
|
|
44
|
+
### Phase 3: DESIGN -- Recommend Cache Strategies and Key Schemas
|
|
45
|
+
|
|
46
|
+
1. **Select the cache strategy per resource.** Based on the access pattern analysis:
|
|
47
|
+
- **Cache-aside (lazy loading):** Application checks cache first, loads from database on miss, populates cache. Best for read-heavy data with tolerance for occasional staleness.
|
|
48
|
+
- **Write-through:** Application writes to cache and database simultaneously. Best for data that must be fresh on the next read.
|
|
49
|
+
- **Write-behind (write-back):** Application writes to cache, cache asynchronously flushes to database. Best for write-heavy workloads where some data loss risk is acceptable.
|
|
50
|
+
- **Read-through:** Cache itself loads from the database on miss. Best when using a cache framework that supports it (e.g., Spring Cache, NestJS CacheModule).
|
|
51
|
+
|
|
52
|
+
2. **Design the key schema.** Produce a key naming convention: `{service}:{resource}:{identifier}:{variant}`. Examples: `api:user:123:profile`, `api:products:list:page=1&limit=20`, `api:config:feature-flags:v2`. Include version suffixes for keys whose structure may change during deployments.
|
|
53
|
+
|
|
54
|
+
3. **Design invalidation strategy.** For each cached resource:
|
|
55
|
+
- **TTL-based:** Set a TTL that balances freshness with hit rate. Include jitter (randomize TTL +/- 10%) to prevent synchronized expiration.
|
|
56
|
+
- **Event-based:** Invalidate on write events. Wire cache invalidation into the write path or subscribe to database change events.
|
|
57
|
+
- **Tag-based:** Group related keys with tags. Invalidate all keys with a tag in a single operation (e.g., invalidate all `user:123:*` keys when user 123 updates their profile).
|
|
58
|
+
|
|
59
|
+
4. **Design thundering herd protection.** For high-traffic keys, implement one or more: lock-based recomputation (only one request rebuilds the cache, others wait), stale-while-revalidate (serve stale data while rebuilding in background), probabilistic early expiration (some requests refresh before TTL expires), or request coalescing (deduplicate identical concurrent requests).
|
|
60
|
+
|
|
61
|
+
5. **Design cache warming.** WHERE the application has predictable traffic patterns (e.g., morning spike), THEN recommend preloading popular cache keys during low-traffic periods. Define the warming strategy: full preload, top-N most accessed keys, or on-deploy warming for critical paths.
|
|
62
|
+
|
|
63
|
+
### Phase 4: VALIDATE -- Verify Consistency and Failure Modes
|
|
64
|
+
|
|
65
|
+
1. **Verify invalidation completeness.** For every write path that modifies cacheable data, confirm that the corresponding cache keys are invalidated. Trace through the code: database write -> cache invalidation. Flag any write path that modifies data without invalidating the cache.
|
|
66
|
+
|
|
67
|
+
2. **Test cache failure gracefully.** WHERE Redis or Memcached is unavailable, THEN the application must degrade gracefully to database-only mode, not crash. Check for try/catch around cache operations. WHERE cache errors bubble up as 500 errors to the user, THEN flag the missing fallback.
|
|
68
|
+
|
|
69
|
+
3. **Verify serialization roundtrip.** WHERE objects are cached as JSON, THEN verify that `JSON.parse(JSON.stringify(obj))` preserves all fields. Common losses: Date objects become strings, undefined fields are dropped, BigInt values throw. Flag any cached type that does not survive a serialization roundtrip.
|
|
70
|
+
|
|
71
|
+
4. **Check distributed cache consistency.** WHERE multiple application instances share a Redis cache, THEN verify: cache writes use appropriate Redis data structures (not race-prone read-modify-write), cache keys include a deployment version to prevent stale reads after schema changes, and Redis is configured with an appropriate eviction policy (`allkeys-lru` for general caching, `volatile-lru` for TTL-based).
|
|
72
|
+
|
|
73
|
+
5. **Validate HTTP caching headers.** For API responses that include `Cache-Control`, verify: `private` is set for user-specific data, `no-store` is set for sensitive data, `max-age` matches the backend TTL, `ETag` or `Last-Modified` headers enable conditional requests, and `Vary` headers include all relevant dimensions (e.g., `Vary: Authorization` for user-specific responses).
|
|
74
|
+
|
|
75
|
+
## Harness Integration
|
|
76
|
+
|
|
77
|
+
- **`harness validate`** -- Run after modifying cache configuration to confirm project health
|
|
78
|
+
- **`harness scan`** -- Refresh the knowledge graph after adding cache modules
|
|
79
|
+
- **`query_graph`** -- Trace which modules read from and write to a cached resource
|
|
80
|
+
- **`get_impact`** -- Understand blast radius when modifying a shared cache key schema
|
|
81
|
+
|
|
82
|
+
## Success Criteria
|
|
83
|
+
|
|
84
|
+
- Cache backends were correctly detected or explicitly specified
|
|
85
|
+
- All existing cache usage was mapped with key patterns, TTLs, and invalidation logic
|
|
86
|
+
- Every cached resource has a defined strategy (cache-aside, write-through, etc.)
|
|
87
|
+
- Cache key schema uses namespaced, versioned keys with no collision risk
|
|
88
|
+
- Invalidation covers every write path that modifies cached data
|
|
89
|
+
- Thundering herd protection is in place for high-traffic keys
|
|
90
|
+
- Cache failure degrades gracefully (no 500 errors when Redis is down)
|
|
91
|
+
- HTTP caching headers are correct for user-specific vs public data
|
|
92
|
+
- No unbounded caches exist without maxSize or eviction policy
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
### Example: Redis Cache-Aside for User Profiles in Express
|
|
97
|
+
|
|
98
|
+
**Input:** "Add Redis caching for user profile lookups in our Express API."
|
|
99
|
+
|
|
100
|
+
**Phase 1 -- DETECT:**
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Backend: Redis 7.x (ioredis 5.x, docker-compose with redis:7-alpine)
|
|
104
|
+
Existing cache usage: none (all reads hit PostgreSQL directly)
|
|
105
|
+
Access pattern: read-heavy (profile viewed ~100x per write)
|
|
106
|
+
Framework: Express 4.x, Prisma ORM
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Phase 3 -- DESIGN:**
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// src/cache/redis.ts
|
|
113
|
+
import Redis from 'ioredis';
|
|
114
|
+
|
|
115
|
+
const redis = new Redis(process.env.REDIS_URL, {
|
|
116
|
+
maxRetriesPerRequest: 1, // fail fast on Redis errors
|
|
117
|
+
enableReadyCheck: true,
|
|
118
|
+
lazyConnect: true,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// src/cache/user-cache.ts
|
|
122
|
+
const USER_TTL = 300; // 5 minutes
|
|
123
|
+
const USER_TTL_JITTER = 30; // +/- 30 seconds to prevent synchronized expiry
|
|
124
|
+
|
|
125
|
+
function userCacheKey(userId: string): string {
|
|
126
|
+
return `api:user:${userId}:profile:v1`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function getCachedUser(userId: string): Promise<User | null> {
|
|
130
|
+
try {
|
|
131
|
+
const cached = await redis.get(userCacheKey(userId));
|
|
132
|
+
if (cached) return JSON.parse(cached);
|
|
133
|
+
return null;
|
|
134
|
+
} catch {
|
|
135
|
+
// Cache failure: degrade to database
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function setCachedUser(userId: string, user: User): Promise<void> {
|
|
141
|
+
try {
|
|
142
|
+
const jitter = Math.floor(Math.random() * USER_TTL_JITTER * 2) - USER_TTL_JITTER;
|
|
143
|
+
await redis.setex(userCacheKey(userId), USER_TTL + jitter, JSON.stringify(user));
|
|
144
|
+
} catch {
|
|
145
|
+
// Cache write failure: log and continue
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function invalidateUserCache(userId: string): Promise<void> {
|
|
150
|
+
try {
|
|
151
|
+
await redis.del(userCacheKey(userId));
|
|
152
|
+
} catch {
|
|
153
|
+
// Cache invalidation failure: TTL will expire the stale entry
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Invalidation wiring:**
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// src/routes/users.ts -- PATCH /users/:id
|
|
162
|
+
app.patch('/users/:id', async (req, res) => {
|
|
163
|
+
const user = await prisma.user.update({ where: { id: req.params.id }, data: req.body });
|
|
164
|
+
await invalidateUserCache(req.params.id); // invalidate after write
|
|
165
|
+
res.json({ data: user });
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Phase 4 -- VALIDATE:**
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Invalidation: PASS -- PATCH /users/:id and DELETE /users/:id both call invalidateUserCache
|
|
173
|
+
Failure mode: PASS -- all cache operations wrapped in try/catch, degrade to DB
|
|
174
|
+
Serialization: WARN -- User.createdAt is a Date object, will become a string after JSON roundtrip
|
|
175
|
+
-> Recommend: parse dates in getCachedUser or use superjson for serialization
|
|
176
|
+
Distributed: PASS -- stateless cache-aside, no read-modify-write races
|
|
177
|
+
HTTP headers: INFO -- consider adding Cache-Control: private, max-age=300 to GET /users/:id response
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Example: HTTP Caching for a Next.js API
|
|
181
|
+
|
|
182
|
+
**Input:** "Configure caching headers for our Next.js API routes."
|
|
183
|
+
|
|
184
|
+
**Phase 1 -- DETECT:**
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
Backend: Vercel Edge Cache (detected vercel.json)
|
|
188
|
+
Existing cache usage: no Cache-Control headers on API routes
|
|
189
|
+
CDN: Vercel Edge Network (automatic)
|
|
190
|
+
Routes analyzed: GET /api/products (public), GET /api/cart (user-specific), GET /api/config (rarely changes)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Phase 3 -- DESIGN:**
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// GET /api/products -- public, cacheable
|
|
197
|
+
export async function GET() {
|
|
198
|
+
const products = await db.product.findMany();
|
|
199
|
+
return Response.json(
|
|
200
|
+
{ data: products },
|
|
201
|
+
{
|
|
202
|
+
headers: {
|
|
203
|
+
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
|
|
204
|
+
Vary: 'Accept-Encoding',
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// GET /api/cart -- user-specific, private
|
|
211
|
+
export async function GET(req: Request) {
|
|
212
|
+
const cart = await getCartForUser(req);
|
|
213
|
+
return Response.json(
|
|
214
|
+
{ data: cart },
|
|
215
|
+
{
|
|
216
|
+
headers: {
|
|
217
|
+
'Cache-Control': 'private, no-cache', // revalidate every request
|
|
218
|
+
ETag: generateETag(cart),
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// GET /api/config -- rarely changes, long cache
|
|
225
|
+
export async function GET() {
|
|
226
|
+
const config = await db.config.findFirst();
|
|
227
|
+
return Response.json(
|
|
228
|
+
{ data: config },
|
|
229
|
+
{
|
|
230
|
+
headers: {
|
|
231
|
+
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
|
|
232
|
+
},
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Example: Distributed Cache Stampede Protection
|
|
239
|
+
|
|
240
|
+
**Input:** "Our product listing page causes a cache stampede every 5 minutes when the Redis key expires."
|
|
241
|
+
|
|
242
|
+
**Phase 2 -- ANALYZE:**
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
Key: api:products:list:all (TTL: 300s)
|
|
246
|
+
Read frequency: ~200 requests/second
|
|
247
|
+
Rebuild cost: 450ms (joins across 3 PostgreSQL tables)
|
|
248
|
+
Problem: when TTL expires, ~50 concurrent requests all trigger the same DB query
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Phase 3 -- DESIGN (stampede protection):**
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Probabilistic early expiration (XFetch algorithm)
|
|
255
|
+
async function getProducts(): Promise<Product[]> {
|
|
256
|
+
const raw = await redis.hgetall('api:products:list:all:v1');
|
|
257
|
+
|
|
258
|
+
if (raw && raw.data) {
|
|
259
|
+
const expiry = Number(raw.expiry);
|
|
260
|
+
const delta = Number(raw.delta); // time to recompute in ms
|
|
261
|
+
const beta = 1.0; // tuning parameter
|
|
262
|
+
|
|
263
|
+
// Probabilistically recompute before actual expiry
|
|
264
|
+
const now = Date.now();
|
|
265
|
+
const shouldRecompute = now - delta * beta * Math.log(Math.random()) >= expiry;
|
|
266
|
+
|
|
267
|
+
if (!shouldRecompute) {
|
|
268
|
+
return JSON.parse(raw.data);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Recompute with distributed lock
|
|
273
|
+
const lock = await redis.set('lock:products:list', '1', 'EX', 10, 'NX');
|
|
274
|
+
if (!lock) {
|
|
275
|
+
// Another instance is recomputing, serve stale if available
|
|
276
|
+
if (raw?.data) return JSON.parse(raw.data);
|
|
277
|
+
// No stale data, wait briefly and retry
|
|
278
|
+
await sleep(100);
|
|
279
|
+
return getProducts();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const start = Date.now();
|
|
283
|
+
const products = await db.product.findMany({ include: { category: true, images: true } });
|
|
284
|
+
const delta = Date.now() - start;
|
|
285
|
+
|
|
286
|
+
await redis.hmset('api:products:list:all:v1', {
|
|
287
|
+
data: JSON.stringify(products),
|
|
288
|
+
expiry: String(Date.now() + 300_000),
|
|
289
|
+
delta: String(delta),
|
|
290
|
+
});
|
|
291
|
+
await redis.expire('api:products:list:all:v1', 600); // hard expiry 2x TTL
|
|
292
|
+
await redis.del('lock:products:list');
|
|
293
|
+
|
|
294
|
+
return products;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Gates
|
|
299
|
+
|
|
300
|
+
- **No unbounded caches.** Every cache (in-memory, Redis, Memcached) must have either a `maxSize`/`maxmemory` limit or a TTL on every key. An unbounded cache will grow until it causes memory exhaustion. WHERE a cache has no eviction policy configured, THEN the skill must halt and require one before proceeding.
|
|
301
|
+
- **Cache failure must not crash the application.** WHERE a cache operation (get, set, del) is not wrapped in error handling, THEN the skill must halt. Cache backends are external dependencies that fail independently. An unhandled Redis connection error must not return a 500 to the user.
|
|
302
|
+
- **Invalidation must cover every write path.** WHERE a cached resource can be modified through multiple code paths (API endpoint, background job, admin panel) and any path lacks invalidation, THEN the skill must flag the gap. Partial invalidation is worse than no caching -- it serves confidently wrong data.
|
|
303
|
+
|
|
304
|
+
## Escalation
|
|
305
|
+
|
|
306
|
+
- **Stale data causing business impact:** When analysis reveals cached data could be stale for longer than the business tolerates (e.g., pricing data cached for 5 minutes), report: "Product prices are cached with a 300-second TTL. A price change will not be visible for up to 5 minutes. If this is unacceptable, switch to write-through caching with event-based invalidation for the pricing resource."
|
|
307
|
+
- **Redis memory approaching limit:** When Redis `maxmemory` is configured but eviction policy is `noeviction`, report: "Redis is configured with `maxmemory 256mb` and `noeviction` policy. When memory is full, all SET operations will fail with OOM errors. Change to `allkeys-lru` for general caching or `volatile-lru` if mixing cached and persistent data."
|
|
308
|
+
- **Cache key collision across services:** When multiple services share a Redis instance without key namespacing, report: "Both the user-service and order-service write to key `user:123`. These are different data shapes from different services. Namespace keys by service: `user-svc:user:123` and `order-svc:user:123`."
|
|
309
|
+
- **Serialization data loss detected:** When a cached object contains types that do not survive JSON roundtrip (Date, BigInt, Map, Set, undefined), report: "The `Order` object contains `Date` fields that become strings after JSON serialization. Use `superjson` or a custom serializer, or convert dates before caching and parse on retrieval."
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: harness-caching
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Cache strategies, invalidation patterns, and distributed caching
|
|
4
|
+
cognitive_mode: advisory-guide
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
- on_new_feature
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
tools:
|
|
12
|
+
- Bash
|
|
13
|
+
- Read
|
|
14
|
+
- Write
|
|
15
|
+
- Edit
|
|
16
|
+
- Glob
|
|
17
|
+
- Grep
|
|
18
|
+
cli:
|
|
19
|
+
command: harness skill run harness-caching
|
|
20
|
+
args:
|
|
21
|
+
- name: path
|
|
22
|
+
description: Project root path
|
|
23
|
+
required: false
|
|
24
|
+
- name: strategy
|
|
25
|
+
description: "Cache strategy: cache-aside, write-through, write-behind, read-through. All evaluated when omitted."
|
|
26
|
+
required: false
|
|
27
|
+
- name: backend
|
|
28
|
+
description: "Cache backend: redis, memcached, in-memory. Auto-detected when omitted."
|
|
29
|
+
required: false
|
|
30
|
+
mcp:
|
|
31
|
+
tool: run_skill
|
|
32
|
+
input:
|
|
33
|
+
skill: harness-caching
|
|
34
|
+
path: string
|
|
35
|
+
type: rigid
|
|
36
|
+
tier: 3
|
|
37
|
+
internal: false
|
|
38
|
+
keywords:
|
|
39
|
+
- cache
|
|
40
|
+
- Redis
|
|
41
|
+
- Memcached
|
|
42
|
+
- CDN
|
|
43
|
+
- invalidation
|
|
44
|
+
- TTL
|
|
45
|
+
- cache-aside
|
|
46
|
+
- write-through
|
|
47
|
+
- write-behind
|
|
48
|
+
- memoization
|
|
49
|
+
- HTTP cache
|
|
50
|
+
- ETag
|
|
51
|
+
stack_signals:
|
|
52
|
+
- "redis.config.*"
|
|
53
|
+
- "src/**/cache/**"
|
|
54
|
+
- "src/**/*cache*"
|
|
55
|
+
- "docker-compose.*redis*"
|
|
56
|
+
- "docker-compose.*memcached*"
|
|
57
|
+
phases:
|
|
58
|
+
- name: detect
|
|
59
|
+
description: Identify existing cache usage, backends, and access patterns
|
|
60
|
+
required: true
|
|
61
|
+
- name: analyze
|
|
62
|
+
description: Evaluate cache hit ratios, TTL policies, and invalidation correctness
|
|
63
|
+
required: true
|
|
64
|
+
- name: design
|
|
65
|
+
description: Recommend cache strategies, key schemas, and eviction policies
|
|
66
|
+
required: true
|
|
67
|
+
- name: validate
|
|
68
|
+
description: Verify cache consistency, thundering herd protection, and failure modes
|
|
69
|
+
required: true
|
|
70
|
+
state:
|
|
71
|
+
persistent: false
|
|
72
|
+
files: []
|
|
73
|
+
depends_on: []
|