@1aboveio/skills 1.0.8 → 1.0.9

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.
Files changed (214) hide show
  1. package/.codex-plugin/plugin.json +13 -0
  2. package/.codex-plugin/resources.json +1827 -0
  3. package/README.md +22 -0
  4. package/package.json +9 -2
  5. package/skills/app-dev/airflow/SKILL.md +1 -1
  6. package/skills/app-dev/airflow/release-check.mjs +3 -1
  7. package/skills/app-dev/android-foundation/SKILL.md +1 -1
  8. package/skills/app-dev/android-foundation/release-check.mjs +3 -1
  9. package/skills/app-dev/app-debug/SKILL.md +1 -1
  10. package/skills/app-dev/app-debug/release-check.mjs +3 -1
  11. package/skills/app-dev/better-auth/SKILL.md +1 -1
  12. package/skills/app-dev/better-auth/release-check.mjs +3 -1
  13. package/skills/app-dev/data-catalog/SKILL.md +1 -1
  14. package/skills/app-dev/data-catalog/release-check.mjs +3 -1
  15. package/skills/app-dev/data-quality/SKILL.md +1 -1
  16. package/skills/app-dev/data-quality/release-check.mjs +3 -1
  17. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  18. package/skills/app-dev/ios-foundation/release-check.mjs +3 -1
  19. package/skills/app-dev/monorepo/SKILL.md +1 -1
  20. package/skills/app-dev/monorepo/release-check.mjs +3 -1
  21. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  22. package/skills/app-dev/nextjs-fullstack/release-check.mjs +3 -1
  23. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  24. package/skills/app-dev/prisma-setup/release-check.mjs +3 -1
  25. package/skills/app-dev/pyspark/SKILL.md +1 -1
  26. package/skills/app-dev/pyspark/release-check.mjs +3 -1
  27. package/skills/app-dev/python-backend/SKILL.md +1 -1
  28. package/skills/app-dev/python-backend/release-check.mjs +3 -1
  29. package/skills/app-dev/shadcn/SKILL.md +1 -1
  30. package/skills/app-dev/shadcn/release-check.mjs +3 -1
  31. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  32. package/skills/app-dev/zod-v4/release-check.mjs +3 -1
  33. package/skills/cicd/cloud-build/SKILL.md +1 -1
  34. package/skills/cicd/cloud-build/release-check.mjs +3 -1
  35. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  36. package/skills/cicd/cloud-debug/release-check.mjs +3 -1
  37. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  38. package/skills/cicd/cloud-deploy/release-check.mjs +3 -1
  39. package/skills/cicd/docker/SKILL.md +1 -1
  40. package/skills/cicd/docker/release-check.mjs +3 -1
  41. package/skills/cicd/github-actions/SKILL.md +1 -1
  42. package/skills/cicd/github-actions/release-check.mjs +3 -1
  43. package/skills/cicd/github-flow/SKILL.md +1 -1
  44. package/skills/cicd/github-flow/release-check.mjs +3 -1
  45. package/skills/cicd/google-cloud/SKILL.md +1 -1
  46. package/skills/cicd/google-cloud/release-check.mjs +3 -1
  47. package/skills/cicd/mergify/SKILL.md +1 -1
  48. package/skills/cicd/mergify/release-check.mjs +3 -1
  49. package/skills/cicd/podman/SKILL.md +1 -1
  50. package/skills/cicd/podman/release-check.mjs +3 -1
  51. package/skills/content/article-review/SKILL.md +1 -1
  52. package/skills/content/article-review/release-check.mjs +3 -1
  53. package/skills/content/article-to-image/SKILL.md +1 -1
  54. package/skills/content/article-to-image/release-check.mjs +3 -1
  55. package/skills/content/flowchart-svg/SKILL.md +1 -1
  56. package/skills/content/flowchart-svg/release-check.mjs +3 -1
  57. package/skills/content/image-gen/SKILL.md +1 -1
  58. package/skills/content/image-gen/release-check.mjs +3 -1
  59. package/skills/content/mermaid/SKILL.md +1 -1
  60. package/skills/content/mermaid/release-check.mjs +3 -1
  61. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  62. package/skills/content/wechat-article-writer/release-check.mjs +3 -1
  63. package/skills/content/wechat-publisher/SKILL.md +1 -1
  64. package/skills/content/wechat-publisher/release-check.mjs +3 -1
  65. package/skills/content/wechat-search/SKILL.md +1 -1
  66. package/skills/content/wechat-search/release-check.mjs +3 -1
  67. package/skills/content/xai-search/SKILL.md +88 -13
  68. package/skills/content/xai-search/release-check.mjs +3 -1
  69. package/skills/content/xai-search/scripts/xai_search.sh +125 -149
  70. package/skills/core/distill-writing/SKILL.md +1 -1
  71. package/skills/core/distill-writing/release-check.mjs +3 -1
  72. package/skills/core/doc-to-md/SKILL.md +1 -1
  73. package/skills/core/doc-to-md/release-check.mjs +3 -1
  74. package/skills/core/editorial-review/SKILL.md +1 -1
  75. package/skills/core/editorial-review/release-check.mjs +3 -1
  76. package/skills/core/house-style/SKILL.md +1 -1
  77. package/skills/core/house-style/release-check.mjs +3 -1
  78. package/skills/core/plain-language/SKILL.md +1 -1
  79. package/skills/core/plain-language/release-check.mjs +3 -1
  80. package/skills/core/polish-cn/SKILL.md +1 -1
  81. package/skills/core/polish-cn/release-check.mjs +3 -1
  82. package/skills/core/reg-parser/SKILL.md +1 -1
  83. package/skills/core/reg-parser/release-check.mjs +3 -1
  84. package/skills/core/terminology/SKILL.md +1 -1
  85. package/skills/core/terminology/release-check.mjs +3 -1
  86. package/skills/core/write-doc/SKILL.md +1 -1
  87. package/skills/core/write-doc/release-check.mjs +3 -1
  88. package/skills/engineering/better-review/SKILL.md +1 -1
  89. package/skills/engineering/better-review/release-check.mjs +3 -1
  90. package/skills/engineering/contributing/SKILL.md +1 -1
  91. package/skills/engineering/contributing/release-check.mjs +3 -1
  92. package/skills/engineering/e2e-test/SKILL.md +1 -1
  93. package/skills/engineering/e2e-test/release-check.mjs +3 -1
  94. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  95. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  96. package/skills/engineering/engineering-runtime/release-check.mjs +3 -1
  97. package/skills/engineering/engineering-runtime/scripts/installation-resolver.mjs +191 -0
  98. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +51 -10
  99. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  100. package/skills/engineering/ensure-coverage/release-check.mjs +3 -1
  101. package/skills/engineering/golden-path/SKILL.md +1 -1
  102. package/skills/engineering/golden-path/release-check.mjs +3 -1
  103. package/skills/engineering/harness-runtime/SKILL.md +1 -1
  104. package/skills/engineering/harness-runtime/release-check.mjs +3 -1
  105. package/skills/engineering/resolve-issues/SKILL.md +1 -1
  106. package/skills/engineering/resolve-issues/references/preflight.md +7 -0
  107. package/skills/engineering/resolve-issues/references/shared-modules.md +27 -0
  108. package/skills/engineering/resolve-issues/references/task-plan.md +5 -1
  109. package/skills/engineering/resolve-issues/release-check.mjs +3 -1
  110. package/skills/engineering/resolve-issues/scripts/active-installation.mjs +32 -0
  111. package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +3 -0
  112. package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +17 -1
  113. package/skills/engineering/resolve-release/SKILL.md +1 -1
  114. package/skills/engineering/resolve-release/release-check.mjs +3 -1
  115. package/skills/engineering/rush-issues/SKILL.md +1 -1
  116. package/skills/engineering/rush-issues/release-check.mjs +3 -1
  117. package/skills/engineering/rush-release/SKILL.md +1 -1
  118. package/skills/engineering/rush-release/release-check.mjs +3 -1
  119. package/skills/engineering/test-quality/SKILL.md +1 -1
  120. package/skills/engineering/test-quality/release-check.mjs +3 -1
  121. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  122. package/skills/risk-compliance/compliance-audit/release-check.mjs +3 -1
  123. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  124. package/skills/risk-compliance/contract-compare/release-check.mjs +3 -1
  125. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  126. package/skills/risk-compliance/contract-review/release-check.mjs +3 -1
  127. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  128. package/skills/risk-compliance/doc-authenticity/release-check.mjs +3 -1
  129. package/skills/risk-compliance/fraud-analysis/SKILL.md +1 -1
  130. package/skills/risk-compliance/fraud-analysis/release-check.mjs +3 -1
  131. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  132. package/skills/risk-compliance/payment-analysis/release-check.mjs +3 -1
  133. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  134. package/skills/risk-compliance/similar-domain/release-check.mjs +3 -1
  135. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
  136. package/skills/risk-compliance/tld-detection/release-check.mjs +3 -1
  137. package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +0 -436
  138. package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +0 -36
  139. package/skills/app-dev/data-quality/scripts/data-quality.test.mjs +0 -12
  140. package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +0 -637
  141. package/skills/cicd/github-flow/scripts/flow.test.mjs +0 -114
  142. package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +0 -108
  143. package/skills/cicd/mergify/scripts/audit.test.mjs +0 -201
  144. package/skills/cicd/mergify/scripts/entrypoints.test.mjs +0 -106
  145. package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +0 -30
  146. package/skills/cicd/mergify/scripts/stack-push.test.mjs +0 -233
  147. package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +0 -1826
  148. package/skills/content/image-gen/scripts/credentials.test.mjs +0 -212
  149. package/skills/content/image-gen/scripts/options.test.mjs +0 -245
  150. package/skills/content/xai-search/tests/smoke_test.sh +0 -36
  151. package/skills/core/polish-cn/scripts/polish-cn.test.mjs +0 -244
  152. package/skills/core/reg-parser/scripts/reg-parser.test.mjs +0 -165
  153. package/skills/engineering/better-review/scripts/pr-context.test.mjs +0 -168
  154. package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +0 -587
  155. package/skills/engineering/better-review/scripts/scan-diff.test.mjs +0 -414
  156. package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +0 -96
  157. package/skills/engineering/contributing/scripts/persist-conventions.test.mjs +0 -118
  158. package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +0 -106
  159. package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +0 -117
  160. package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +0 -69
  161. package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +0 -98
  162. package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +0 -71
  163. package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +0 -59
  164. package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +0 -76
  165. package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +0 -68
  166. package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +0 -95
  167. package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +0 -288
  168. package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +0 -96
  169. package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +0 -96
  170. package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +0 -47
  171. package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +0 -86
  172. package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +0 -447
  173. package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +0 -552
  174. package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +0 -289
  175. package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +0 -119
  176. package/skills/engineering/golden-path/scripts/golden-path.test.mjs +0 -1457
  177. package/skills/engineering/harness-runtime/discover-models.test.mjs +0 -363
  178. package/skills/engineering/harness-runtime/harness-runtime.test.mjs +0 -967
  179. package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +0 -829
  180. package/skills/engineering/harness-runtime/model-catalog.test.mjs +0 -366
  181. package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +0 -280
  182. package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +0 -346
  183. package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +0 -88
  184. package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +0 -264
  185. package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +0 -79
  186. package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +0 -107
  187. package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +0 -14
  188. package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +0 -149
  189. package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +0 -915
  190. package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +0 -156
  191. package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +0 -448
  192. package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +0 -217
  193. package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +0 -91
  194. package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +0 -1060
  195. package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +0 -458
  196. package/skills/engineering/resolve-release/scripts/apply.test.mjs +0 -99
  197. package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +0 -100
  198. package/skills/engineering/resolve-release/scripts/flow.test.mjs +0 -340
  199. package/skills/engineering/resolve-release/scripts/green-head.test.mjs +0 -101
  200. package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +0 -426
  201. package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +0 -659
  202. package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +0 -317
  203. package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +0 -291
  204. package/skills/engineering/resolve-release/scripts/plan.test.mjs +0 -428
  205. package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +0 -591
  206. package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +0 -119
  207. package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +0 -104
  208. package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +0 -14
  209. package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +0 -12
  210. package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +0 -212
  211. package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +0 -14
  212. package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +0 -14
  213. package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +0 -134
  214. package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +0 -520
@@ -1,86 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
-
4
- import { auditCorpus, buildAdoptionPlan, classifySmoke, renderAdoptionIssue } from './ci-audit.mjs'
5
-
6
- const file = (name, text) => ({ name, text })
7
-
8
- test('blocking golden-path smoke passes', () => {
9
- const report = auditCorpus([file('.github/workflows/ci.yml', `
10
- jobs:
11
- smoke:
12
- steps:
13
- - run: node smoke.mjs verdict --manifest smoke.manifest.json --target local --results smoke-results.json
14
- `)])
15
- assert.equal(report.ok, true)
16
- assert.equal(report.smoke.status, 'present')
17
- })
18
-
19
- test('the generated golden-path workflow counts as the smoke gate', () => {
20
- const report = auditCorpus([file('.github/workflows/golden-paths.yml', `
21
- jobs:
22
- golden-paths:
23
- steps:
24
- - run: node scripts/golden-paths/golden-path.mjs verdict --profile "$GOLDEN_PATH_PROFILE" --target "$BASE_URL"
25
- `)])
26
- assert.equal(report.ok, true)
27
- assert.equal(report.smoke.status, 'present')
28
- })
29
-
30
- test('the former coverage gates are ignored', () => {
31
- const report = auditCorpus([file('.github/workflows/ci.yml', `
32
- - run: node coverage-ledger.mjs validate
33
- - run: node presentation-sweep.mjs
34
- - run: pnpm playwright test
35
- - run: node lint-tests.mjs --rules mock-internal-seam
36
- - run: node check-quarantine-expiry.mjs
37
- `)])
38
- assert.equal(report.ok, false)
39
- assert.equal(report.smoke.status, 'absent')
40
- assert.deepEqual(Object.keys(report), ['smoke', 'ok', 'scanned'])
41
- })
42
-
43
- test('a weakened smoke job is warn-only and fails by default', () => {
44
- const report = auditCorpus([file('cloudbuild.yaml', `
45
- - id: smoke
46
- allowFailure: true
47
- args: ['-c', 'node smoke.mjs verdict --manifest smoke.manifest.json --results smoke-results.json']
48
- `)])
49
- assert.equal(report.ok, false)
50
- assert.equal(report.smoke.status, 'warn-only')
51
- })
52
-
53
- test('--allow-warn accepts warn-only smoke when explicitly requested', () => {
54
- const report = auditCorpus([file('ci.yml', 'run: node smoke.mjs verdict --results out.json || true')], { allowWarn: true })
55
- assert.equal(report.ok, true)
56
- })
57
-
58
- test('comments do not count as smoke wiring or weakening', () => {
59
- const absent = auditCorpus([file('ci.yml', '# node smoke.mjs verdict --results out.json')])
60
- assert.equal(absent.smoke.status, 'absent')
61
-
62
- const corpus = [{ name: 'ci.yml', lines: [
63
- '# never add continue-on-error: true',
64
- 'run: node smoke.mjs verdict --results out.json',
65
- ] }]
66
- assert.equal(classifySmoke(corpus).status, 'present')
67
- })
68
-
69
- test('weakening far from smoke does not bleed into its status', () => {
70
- const lines = ['continue-on-error: true', ...Array.from({ length: 20 }, (_, index) => `# filler ${index}`), 'run: smoke-gate']
71
- assert.equal(classifySmoke([{ name: 'ci.yml', lines }]).status, 'present')
72
- })
73
-
74
- test('adoption output requests only golden-path smoke', () => {
75
- const report = auditCorpus([file('.github/workflows/ci.yml', 'run: node coverage-ledger.mjs validate')])
76
- const plan = buildAdoptionPlan(report)
77
- const body = renderAdoptionIssue(plan)
78
- assert.equal(plan.needed, true)
79
- assert.match(body, /Wire golden-path smoke into CI/)
80
- assert.doesNotMatch(body, /coverage-ledger|presentation sweep|quarantine expiry|all-gates|static-gates/)
81
- })
82
-
83
- test('adoption is unnecessary when smoke is blocking', () => {
84
- const report = auditCorpus([file('ci.yml', 'run: smoke-gate')])
85
- assert.equal(buildAdoptionPlan(report).needed, false)
86
- })
@@ -1,447 +0,0 @@
1
- // Tests for the Coverage Ledger reference tool, focused on the Presentation axis
2
- // spine (issue #195). Run: `node --test` from scripts/, or `npm test`.
3
-
4
- import { test } from 'node:test'
5
- import assert from 'node:assert/strict'
6
- import fs from 'node:fs'
7
- import os from 'node:os'
8
- import path from 'node:path'
9
-
10
- import {
11
- depthStatus, baselineFor, build, PRESENTATION_VIEWPORT_FLOOR,
12
- isPresentationLevel, presentationEscalation, applyCellExclusions, computeMetrics,
13
- satisfies, PRESENTATION_LEVELS, PRESENTATION_ROUTE_FLOOR,
14
- } from './coverage-ledger.mjs'
15
-
16
- // `presentation:fidelity` is doctrine in references/presentation/axis.md. Doctrine
17
- // that names a graded token the grader has never heard of is the exact failure this
18
- // skill family keeps re-learning: the prose reads enforced, the machinery ignores it.
19
- test('presentation:fidelity is a registered, opt-in, exact-match level', () => {
20
- assert.ok(PRESENTATION_LEVELS.has('presentation:fidelity'), 'the grader knows the token')
21
- assert.ok(isPresentationLevel('presentation:fidelity'), 'and grades it real-render like its siblings')
22
- assert.ok(!PRESENTATION_ROUTE_FLOOR.includes('presentation:fidelity'), 'opt-in: a surface earns it by citing a design source, not by being a route')
23
-
24
- // Exact-match in both directions. The tempting substitution is `presentation:visual`
25
- // ("we have a baseline, isn't that the same check?") — it is not: a baseline
26
- // captured from the built page ratifies whatever shipped, which is the failure
27
- // fidelity exists to catch.
28
- assert.ok(satisfies(['presentation:fidelity'], 'presentation:fidelity'))
29
- assert.ok(!satisfies(['presentation:visual'], 'presentation:fidelity'))
30
- assert.ok(!satisfies(['presentation:fidelity'], 'presentation:visual'))
31
- assert.ok(!satisfies(['browser-journey', 'e2e'], 'presentation:fidelity'), 'a functional journey does not prove it')
32
- })
33
-
34
- test('presentation:fidelity grades like its siblings: DOM-only is Over-mocked, real-render needs attestation', () => {
35
- // A JSDOM test cannot read computed style off a laid-out page, so it can only ever
36
- // restate the manifest back to itself — the axis's over-mock.
37
- const domOnly = depthStatus(['presentation:fidelity'], [{ levels: ['presentation:fidelity'], realBrowser: false, intercepts: false }])
38
- assert.equal(domOnly.status, 'Over-mocked')
39
- assert.match(domOnly.note, /real rendered-page evidence/)
40
-
41
- // Real browser, self-declared → Unverified until the test is marked read, the
42
- // same promotion path every presentation level takes.
43
- const t = [{ levels: ['presentation:fidelity'], realBrowser: true, intercepts: false }]
44
- assert.equal(depthStatus(['presentation:fidelity'], t).status, 'Unverified')
45
- assert.equal(depthStatus(['presentation:fidelity'], t, { attested: true }).status, 'Covered')
46
- })
47
-
48
- // A synthetic scanned-test entry, matching what scanTests() produces.
49
- function t(levels, { intercepts = false, realBrowser = false, domOnly = false } = {}) {
50
- return { file: 'x.spec.ts', levels: new Set(levels), intercepts, realBrowser, domOnly }
51
- }
52
-
53
- // ---------- baseline: every browser route auto-owes presentation:spatial ----------
54
-
55
- test('browser routes carry the presentation floor for every class', () => {
56
- for (const cls of ['read', 'detail', 'mutation']) {
57
- const floor = baselineFor('route', cls)
58
- assert.ok(floor.includes('browser-journey'), `${cls} keeps functional floor`)
59
- assert.ok(floor.includes('presentation:render-health'), `${cls} gains render-health spine`)
60
- assert.ok(floor.includes('presentation:spatial'), `${cls} gains spatial floor`)
61
- assert.ok(floor.includes('presentation:perceivability'), `${cls} gains perceivability floor`)
62
- assert.ok(floor.includes('presentation:reachability'), `${cls} gains reachability floor`)
63
- assert.ok(floor.includes('presentation:temporal'), `${cls} gains temporal floor`)
64
- }
65
- })
66
-
67
- test('render-health is the spine (first presentation level on the floor)', () => {
68
- const floor = baselineFor('route', 'read')
69
- const firstPresentation = floor.find((l) => l.startsWith('presentation:'))
70
- assert.equal(firstPresentation, 'presentation:render-health')
71
- })
72
-
73
- test('render-health grades like a presentation level (real render required)', () => {
74
- const RH = ['presentation:render-health']
75
- // a real-browser, non-intercepting test, marked read (verified) → Covered
76
- assert.equal(depthStatus(RH, [t(['presentation:render-health'], { realBrowser: true })], { attested: true }).status, 'Covered')
77
- // DOM-only cannot observe a pageerror on real mount → Over-mocked
78
- assert.equal(depthStatus(RH, [t(['presentation:render-health'], { realBrowser: false, domOnly: true })], { attested: true }).status, 'Over-mocked')
79
- // a spec that intercepts first-party traffic does not prove the real page renders
80
- assert.equal(depthStatus(RH, [t(['presentation:render-health'], { realBrowser: true, intercepts: true })], { attested: true }).status, 'Over-mocked')
81
- })
82
-
83
- test('render-health breadth floor unifies the old `smoke` token (back-compat alias)', () => {
84
- // the renamed token satisfies the floor
85
- assert.notEqual(depthStatus(['render-health'], [t(['render-health'], { realBrowser: true })], { attested: true }).status, 'Missing')
86
- // a legacy `@level smoke` tag still satisfies a render-health floor (alias)
87
- assert.notEqual(depthStatus(['render-health'], [t(['smoke'], { realBrowser: true })], { attested: true }).status, 'Missing')
88
- // and a render-health tag satisfies a legacy `smoke` floor (reverse alias)
89
- assert.notEqual(depthStatus(['smoke'], [t(['render-health'], { realBrowser: true })], { attested: true }).status, 'Missing')
90
- // a fuller browser journey also satisfies render-health
91
- assert.notEqual(depthStatus(['render-health'], [t(['browser-journey'], { realBrowser: true })], { attested: true }).status, 'Missing')
92
- // no test → Missing (the floor still bites)
93
- assert.equal(depthStatus(['render-health'], [], { attested: true }).status, 'Missing')
94
- })
95
-
96
- // ---------- over-mock rate metric (depth-axis honesty) ----------
97
-
98
- // A synthetic index row, matching what build() stores per surface.
99
- function row(depthStatus, depthNote = '') {
100
- return { surface: 's', depthStatus, depthNote }
101
- }
102
- const idx = (rows) => new Map(rows.map((r, i) => [`s${i}`, r]))
103
-
104
- test('over-mock rate = over-mocked / tested surfaces, behaviour vs presentation split', () => {
105
- const m = computeMetrics(idx([
106
- row('Covered'),
107
- row('Over-mocked', 'behavior level met only by internal interception: api'),
108
- row('Over-mocked', 'presentation level proven without real rendered-page evidence: presentation:spatial'),
109
- row('Wrong Level'),
110
- ]))
111
- assert.equal(m.tested, 4) // all four have tests (none Missing)
112
- assert.equal(m.overMocked, 2)
113
- assert.equal(m.overMockedBehavior, 1)
114
- assert.equal(m.overMockedPresentation, 1)
115
- assert.equal(m.overMockRate, 0.5)
116
- assert.equal(m.overMockRatePct, 50)
117
- })
118
-
119
- test('Missing surfaces are absent, not over-mocked — excluded from the denominator', () => {
120
- // 1 over-mocked, 1 covered (tested=2); two Missing surfaces don't dilute the rate.
121
- const m = computeMetrics(idx([row('Over-mocked', 'behavior level: x'), row('Covered'), row('Missing'), row('Missing')]))
122
- assert.equal(m.tested, 2)
123
- assert.equal(m.overMockRate, 0.5)
124
- })
125
-
126
- test('reachability/excluded/null states are not depth-graded — never counted', () => {
127
- const m = computeMetrics(idx([row('Reached'), row('Dead'), row('Excluded'), row(null), row('Covered')]))
128
- assert.equal(m.depthGraded, 1) // only the Covered row owes a depth check
129
- assert.equal(m.tested, 1)
130
- assert.equal(m.overMocked, 0)
131
- })
132
-
133
- test('rate is 0 (never NaN) when nothing is tested', () => {
134
- const m = computeMetrics(idx([row('Missing'), row('Excluded')]))
135
- assert.equal(m.tested, 0)
136
- assert.equal(m.overMockRate, 0)
137
- assert.equal(m.overMockRatePct, 0)
138
- })
139
-
140
- test('non-browser surfaces do NOT carry a presentation floor', () => {
141
- assert.ok(!baselineFor('api', 'read').includes('presentation:spatial'))
142
- assert.ok(!baselineFor('api', 'mutation').includes('presentation:spatial'))
143
- assert.deepEqual(baselineFor('table'), [])
144
- })
145
-
146
- test('viewport floor is the documented 375 + 1280 pair', () => {
147
- assert.deepEqual(PRESENTATION_VIEWPORT_FLOOR, [375, 1280])
148
- })
149
-
150
- // ---------- depth grading of presentation:spatial ----------
151
-
152
- const SPATIAL = ['presentation:spatial']
153
-
154
- test('real-rendered + marked read (verified) → Covered', () => {
155
- const ds = depthStatus(SPATIAL, [t(['presentation:spatial'], { realBrowser: true })], { attested: true })
156
- assert.equal(ds.status, 'Covered')
157
- })
158
-
159
- test('real-rendered but not marked read → Unverified', () => {
160
- const ds = depthStatus(SPATIAL, [t(['presentation:spatial'], { realBrowser: true })], { attested: false })
161
- assert.equal(ds.status, 'Unverified')
162
- })
163
-
164
- test('DOM-only / JSDOM presentation test → Over-mocked (not Covered)', () => {
165
- const ds = depthStatus(SPATIAL, [t(['presentation:spatial'], { realBrowser: false, domOnly: true })], { attested: true })
166
- assert.equal(ds.status, 'Over-mocked')
167
- assert.match(ds.note, /real rendered-page evidence/)
168
- })
169
-
170
- test('presentation test that intercepts first-party traffic → Over-mocked', () => {
171
- const ds = depthStatus(SPATIAL, [t(['presentation:spatial'], { realBrowser: true, intercepts: true })], { attested: true })
172
- assert.equal(ds.status, 'Over-mocked')
173
- })
174
-
175
- test('a functional browser-journey does NOT satisfy presentation:spatial', () => {
176
- // journey drives the DOM; it never asserts the page is laid out without overflow.
177
- const ds = depthStatus(SPATIAL, [t(['browser-journey'], { realBrowser: true })], { attested: true })
178
- assert.equal(ds.status, 'Wrong Level')
179
- assert.match(ds.note, /presentation:spatial/)
180
- })
181
-
182
- test('no test at all → Missing', () => {
183
- const ds = depthStatus(SPATIAL, [], { attested: true })
184
- assert.equal(ds.status, 'Missing')
185
- })
186
-
187
- // ---------- perceivability behaves like a presentation level ----------
188
-
189
- const PERCEIVE = ['presentation:perceivability']
190
-
191
- test('perceivability: real-rendered + attested → Covered', () => {
192
- const ds = depthStatus(PERCEIVE, [t(['presentation:perceivability'], { realBrowser: true })], { attested: true })
193
- assert.equal(ds.status, 'Covered')
194
- })
195
-
196
- test('perceivability: DOM-only contrast check → Over-mocked', () => {
197
- const ds = depthStatus(PERCEIVE, [t(['presentation:perceivability'], { domOnly: true })], { attested: true })
198
- assert.equal(ds.status, 'Over-mocked')
199
- })
200
-
201
- test('perceivability: a spatial test does not satisfy perceivability', () => {
202
- const ds = depthStatus(PERCEIVE, [t(['presentation:spatial'], { realBrowser: true })], { attested: true })
203
- assert.equal(ds.status, 'Wrong Level')
204
- })
205
-
206
- // ---------- reachability behaves like a presentation level ----------
207
-
208
- const REACH = ['presentation:reachability']
209
-
210
- test('reachability: real-rendered + attested → Covered', () => {
211
- const ds = depthStatus(REACH, [t(['presentation:reachability'], { realBrowser: true })], { attested: true })
212
- assert.equal(ds.status, 'Covered')
213
- })
214
-
215
- test('reachability: DOM-only (no real crawl/render) → Over-mocked', () => {
216
- const ds = depthStatus(REACH, [t(['presentation:reachability'], { domOnly: true })], { attested: true })
217
- assert.equal(ds.status, 'Over-mocked')
218
- })
219
-
220
- // ---------- temporal behaves like a presentation level ----------
221
-
222
- const TEMPORAL = ['presentation:temporal']
223
-
224
- test('temporal: real-rendered + attested → Covered', () => {
225
- const ds = depthStatus(TEMPORAL, [t(['presentation:temporal'], { realBrowser: true })], { attested: true })
226
- assert.equal(ds.status, 'Covered')
227
- })
228
-
229
- test('temporal: real-rendered but NOT marked read → Unverified (the third-party-lane state)', () => {
230
- const ds = depthStatus(TEMPORAL, [t(['presentation:temporal'], { realBrowser: true })], { attested: false })
231
- assert.equal(ds.status, 'Unverified')
232
- })
233
-
234
- test('temporal: DOM-only → Over-mocked', () => {
235
- const ds = depthStatus(TEMPORAL, [t(['presentation:temporal'], { domOnly: true })], { attested: true })
236
- assert.equal(ds.status, 'Over-mocked')
237
- })
238
-
239
- // ---------- feature-derived escalation engine (#200) ----------
240
-
241
- test('isPresentationLevel: prefix-based, covers cell-qualified levels', () => {
242
- assert.equal(isPresentationLevel('presentation:spatial'), true)
243
- assert.equal(isPresentationLevel('presentation:perceivability@dark'), true)
244
- assert.equal(isPresentationLevel('browser-journey'), false)
245
- assert.equal(isPresentationLevel(undefined), false)
246
- })
247
-
248
- test('presentationEscalation: theme toggle → dark perceivability cell', () => {
249
- assert.deepEqual(presentationEscalation({ themeToggle: true }), ['presentation:perceivability@dark'])
250
- })
251
-
252
- test('presentationEscalation: i18n → long-locale + RTL spatial cells', () => {
253
- assert.deepEqual(presentationEscalation({ i18n: true }), ['presentation:spatial@long-locale', 'presentation:spatial@rtl'])
254
- })
255
-
256
- test('presentationEscalation: deterministic (sorted, deduped) and empty for no signals', () => {
257
- assert.deepEqual(presentationEscalation({}), [])
258
- // same signals → identical output regardless of key order
259
- const a = presentationEscalation({ themeToggle: true, i18n: true })
260
- const b = presentationEscalation({ i18n: true, themeToggle: true })
261
- assert.deepEqual(a, b)
262
- assert.deepEqual(a, ['presentation:perceivability@dark', 'presentation:spatial@long-locale', 'presentation:spatial@rtl'])
263
- })
264
-
265
- test('applyCellExclusions: gated removal of an escalated cell yields a census', () => {
266
- const levels = ['presentation:spatial', 'presentation:perceivability@dark']
267
- const r = applyCellExclusions(levels, { 'presentation:perceivability@dark': { category: 'deprecated', reason: 'dark mode being removed' } })
268
- assert.deepEqual(r.kept, ['presentation:spatial'])
269
- assert.equal(r.census.length, 1)
270
- })
271
-
272
- test('applyCellExclusions: cannot exclude a base (unqualified) floor level', () => {
273
- const r = applyCellExclusions(['presentation:spatial'], { 'presentation:spatial': { category: 'x', reason: 'y' } })
274
- assert.deepEqual(r.kept, ['presentation:spatial']) // kept despite the entry
275
- assert.equal(r.rejected.length, 1)
276
- })
277
-
278
- test('applyCellExclusions: escalated cell without category/reason is rejected (kept)', () => {
279
- const levels = ['presentation:perceivability@dark']
280
- const r = applyCellExclusions(levels, { 'presentation:perceivability@dark': { category: 'deprecated' } })
281
- assert.deepEqual(r.kept, ['presentation:perceivability@dark'])
282
- assert.equal(r.rejected.length, 1)
283
- })
284
-
285
- test('build(): a route with a themeToggle signal gains the dark-mode obligation', async () => {
286
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'covesc-'))
287
- try {
288
- const gen = path.join(dir, 'docs/tests/_generated')
289
- fs.mkdirSync(gen, { recursive: true })
290
- fs.writeFileSync(path.join(gen, 'surface-inventory.json'), JSON.stringify({
291
- surfaces: [{ id: '/app', kind: 'route', class: 'read', reachability: 'reachable', signals: { themeToggle: true } }],
292
- }))
293
- const cfg = {
294
- inventory: path.join(gen, 'surface-inventory.json'),
295
- coverageDir: path.join(dir, 'docs/tests'),
296
- testRoots: [dir], requirementGlobs: {}, acceptedMarker: /x/, unverifiedBlocks: true,
297
- }
298
- const { index } = await build(cfg)
299
- const row = index.get('/app')
300
- assert.ok(row.requiredLevels.includes('presentation:perceivability@dark'), 'dark cell auto-added from signal')
301
- assert.ok(row.requiredLevels.includes('presentation:perceivability'), 'base floor still present')
302
- } finally {
303
- fs.rmSync(dir, { recursive: true, force: true })
304
- }
305
- })
306
-
307
- // ---------- end-to-end build() against a temp fixture ----------
308
-
309
- test('build() grades a real browser route end-to-end', async () => {
310
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'covledger-'))
311
- try {
312
- const gen = path.join(dir, 'docs/tests/_generated')
313
- fs.mkdirSync(gen, { recursive: true })
314
- fs.writeFileSync(path.join(gen, 'surface-inventory.json'), JSON.stringify({
315
- surfaces: [{ id: '/dashboard', kind: 'route', class: 'read', reachability: 'reachable' }],
316
- }))
317
- // A real-browser presentation test for the route.
318
- const e2e = path.join(dir, 'e2e')
319
- fs.mkdirSync(e2e, { recursive: true })
320
- // Satisfies ALL route floors: the functional browser-journey plus the full
321
- // presentation floor (render-health spine + spatial, perceivability,
322
- // reachability, temporal), in one real-browser spec.
323
- fs.writeFileSync(path.join(e2e, 'dashboard.spec.ts'), [
324
- '// @covers /dashboard',
325
- '// @level browser-journey',
326
- '// @level presentation:render-health',
327
- '// @level presentation:spatial',
328
- '// @level presentation:perceivability',
329
- '// @level presentation:reachability',
330
- '// @level presentation:temporal',
331
- "import { test, expect } from '@playwright/test'",
332
- "test('renders, stable, perceivable, reachable', async ({ page }) => { await page.goto('/dashboard') })",
333
- ].join('\n'))
334
-
335
- const cfg = {
336
- inventory: path.join(gen, 'surface-inventory.json'),
337
- coverageDir: path.join(dir, 'docs/tests'),
338
- testRoots: [dir],
339
- requirementGlobs: {},
340
- acceptedMarker: /status:\s*accepted/i,
341
- unverifiedBlocks: true,
342
- }
343
- const { index } = await build(cfg)
344
- const row = index.get('/dashboard')
345
- assert.ok(row, 'route is in the index')
346
- assert.ok(row.requiredLevels.includes('presentation:spatial'), 'presentation floor applied')
347
- // real-rendered but not yet marked read → Unverified
348
- assert.equal(row.depthStatus, 'Unverified')
349
- } finally {
350
- fs.rmSync(dir, { recursive: true, force: true })
351
- }
352
- })
353
-
354
- test('build(): Unverified is a warning unless the user opts into unverifiedBlocks', async () => {
355
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'covunv-'))
356
- try {
357
- const gen = path.join(dir, 'docs/tests/_generated')
358
- fs.mkdirSync(gen, { recursive: true })
359
- fs.writeFileSync(path.join(gen, 'surface-inventory.json'), JSON.stringify({
360
- surfaces: [{ id: '/dashboard', kind: 'route', class: 'read', reachability: 'reachable' }],
361
- }))
362
- fs.mkdirSync(path.join(dir, 'e2e'), { recursive: true })
363
- fs.writeFileSync(path.join(dir, 'e2e', 'dashboard.spec.ts'), [
364
- '// @covers /dashboard',
365
- '// @level browser-journey',
366
- '// @level presentation:render-health',
367
- '// @level presentation:spatial',
368
- '// @level presentation:perceivability',
369
- '// @level presentation:reachability',
370
- '// @level presentation:temporal',
371
- "import { test } from '@playwright/test'",
372
- "test('dashboard', async ({ page }) => { await page.goto('/dashboard') })",
373
- ].join('\n'))
374
- const base = {
375
- inventory: path.join(gen, 'surface-inventory.json'),
376
- coverageDir: path.join(dir, 'docs/tests'),
377
- testRoots: [dir], requirementGlobs: {}, acceptedMarker: /x/,
378
- }
379
- const severityOf = async (cfg) => (await build(cfg)).findings
380
- .filter((f) => f.kind === 'Unverified' && f.surface === '/dashboard').map((f) => f.severity)
381
- assert.deepEqual(await severityOf(base), ['warn'])
382
- assert.deepEqual(await severityOf({ ...base, unverifiedBlocks: true }), ['error'])
383
- } finally {
384
- fs.rmSync(dir, { recursive: true, force: true })
385
- }
386
- })
387
-
388
- // ---------- acceptance gate (requirementGlobs) ----------
389
-
390
- test('build(): the acceptance gate holds every accepted ADR to a criteria doc or a tracked gap', async () => {
391
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'covadr-'))
392
- try {
393
- const gen = path.join(dir, 'docs/tests/_generated')
394
- const adr = path.join(dir, 'docs/adr')
395
- const cov = path.join(dir, 'docs/tests/adr')
396
- fs.mkdirSync(gen, { recursive: true }); fs.mkdirSync(adr, { recursive: true }); fs.mkdirSync(cov, { recursive: true })
397
- fs.writeFileSync(path.join(gen, 'surface-inventory.json'), JSON.stringify({ surfaces: [] }))
398
- fs.writeFileSync(path.join(dir, 'docs/tests/0008-criteria.md'), '# criteria')
399
- // 0008: accepted, coverage file links criteria → clean
400
- fs.writeFileSync(path.join(adr, '0008-allowlist.md'), '# ADR 8\nstatus: accepted\n')
401
- fs.writeFileSync(path.join(cov, '0008-allowlist.coverage.json'), JSON.stringify({ criteria: path.join(dir, 'docs/tests/0008-criteria.md'), surfaces: {} }))
402
- // 0009: accepted (bold markdown status form), coverage file with neither criteria nor gap → error
403
- fs.writeFileSync(path.join(adr, '0009-dispatch.md'), '# ADR 9\n**Status:** accepted\n')
404
- fs.writeFileSync(path.join(cov, '0009-dispatch.coverage.json'), JSON.stringify({ surfaces: {} }))
405
- // 0010: accepted, no coverage file at all → error
406
- fs.writeFileSync(path.join(adr, '0010-billing.md'), '# ADR 10\nStatus: Accepted\n')
407
- // 0011: accepted but declares no runtime behavior → exempt
408
- fs.writeFileSync(path.join(adr, '0011-terminology.md'), '# ADR 11\nstatus: accepted\n\nThis ADR has no runtime behavior.\n')
409
- // 0012: accepted, coverage file names a tracked gap instead of criteria → clean
410
- fs.writeFileSync(path.join(adr, '0012-export.md'), '# ADR 12\nstatus: accepted\n')
411
- fs.writeFileSync(path.join(cov, '0012-export.coverage.json'), JSON.stringify({ gapIssue: '#412', surfaces: {} }))
412
- // 0013: draft → ignored
413
- fs.writeFileSync(path.join(adr, '0013-draft.md'), '# ADR 13\nstatus: proposed\n')
414
-
415
- const cfg = {
416
- inventory: path.join(gen, 'surface-inventory.json'),
417
- coverageDir: path.join(dir, 'docs/tests'),
418
- testRoots: [dir],
419
- requirementGlobs: { adr },
420
- acceptedMarker: /\bstatus\b[\s*:_-]{0,6}accepted/i,
421
- unverifiedBlocks: true,
422
- }
423
- const { findings } = await build(cfg)
424
- const gate = findings.filter((f) => f.kind === 'Gate').map((f) => f.surface).sort()
425
- assert.deepEqual(gate, ['adr:0009', 'adr:0010'], `only the placeholder and the missing file fail the gate, got ${JSON.stringify(findings.filter((f) => f.kind === 'Gate'))}`)
426
- assert.ok(!findings.some((f) => f.kind === 'Gate skipped'), 'the gate ran')
427
- } finally {
428
- fs.rmSync(dir, { recursive: true, force: true })
429
- }
430
- })
431
-
432
- test('build(): a requirementGlobs directory that does not exist is a gate error, not a silent skip', async () => {
433
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'covadr-'))
434
- try {
435
- const gen = path.join(dir, 'docs/tests/_generated')
436
- fs.mkdirSync(gen, { recursive: true })
437
- fs.writeFileSync(path.join(gen, 'surface-inventory.json'), JSON.stringify({ surfaces: [] }))
438
- const cfg = {
439
- inventory: path.join(gen, 'surface-inventory.json'), coverageDir: path.join(dir, 'docs/tests'), testRoots: [dir],
440
- requirementGlobs: { adr: path.join(dir, 'docs/adr') }, acceptedMarker: /status:\s*accepted/i, unverifiedBlocks: true,
441
- }
442
- const { findings } = await build(cfg)
443
- assert.ok(findings.some((f) => f.kind === 'Gate' && f.surface === 'adr:*'), 'names the missing directory')
444
- } finally {
445
- fs.rmSync(dir, { recursive: true, force: true })
446
- }
447
- })