@1aboveio/skills 1.0.7 → 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 (224) 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 +92 -34
  8. package/skills/app-dev/android-foundation/assets/android-ci-job.yml +13 -7
  9. package/skills/app-dev/android-foundation/references/ci.md +23 -13
  10. package/skills/app-dev/android-foundation/references/delivery-focus.md +29 -0
  11. package/skills/app-dev/android-foundation/references/diagnosis.md +136 -0
  12. package/skills/app-dev/android-foundation/references/gotchas.md +20 -11
  13. package/skills/app-dev/android-foundation/references/setup.md +15 -6
  14. package/skills/app-dev/android-foundation/release-check.mjs +3 -1
  15. package/skills/app-dev/android-foundation/scripts/device-run.sh +148 -42
  16. package/skills/app-dev/app-debug/SKILL.md +1 -1
  17. package/skills/app-dev/app-debug/release-check.mjs +3 -1
  18. package/skills/app-dev/better-auth/SKILL.md +1 -1
  19. package/skills/app-dev/better-auth/release-check.mjs +3 -1
  20. package/skills/app-dev/data-catalog/SKILL.md +1 -1
  21. package/skills/app-dev/data-catalog/release-check.mjs +3 -1
  22. package/skills/app-dev/data-quality/SKILL.md +1 -1
  23. package/skills/app-dev/data-quality/release-check.mjs +3 -1
  24. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  25. package/skills/app-dev/ios-foundation/release-check.mjs +3 -1
  26. package/skills/app-dev/monorepo/SKILL.md +1 -1
  27. package/skills/app-dev/monorepo/release-check.mjs +3 -1
  28. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  29. package/skills/app-dev/nextjs-fullstack/release-check.mjs +3 -1
  30. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  31. package/skills/app-dev/prisma-setup/release-check.mjs +3 -1
  32. package/skills/app-dev/pyspark/SKILL.md +1 -1
  33. package/skills/app-dev/pyspark/release-check.mjs +3 -1
  34. package/skills/app-dev/python-backend/SKILL.md +1 -1
  35. package/skills/app-dev/python-backend/release-check.mjs +3 -1
  36. package/skills/app-dev/shadcn/SKILL.md +1 -1
  37. package/skills/app-dev/shadcn/release-check.mjs +3 -1
  38. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  39. package/skills/app-dev/zod-v4/release-check.mjs +3 -1
  40. package/skills/cicd/cloud-build/SKILL.md +1 -1
  41. package/skills/cicd/cloud-build/release-check.mjs +3 -1
  42. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  43. package/skills/cicd/cloud-debug/release-check.mjs +3 -1
  44. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  45. package/skills/cicd/cloud-deploy/release-check.mjs +3 -1
  46. package/skills/cicd/docker/SKILL.md +1 -1
  47. package/skills/cicd/docker/release-check.mjs +3 -1
  48. package/skills/cicd/github-actions/SKILL.md +1 -1
  49. package/skills/cicd/github-actions/release-check.mjs +3 -1
  50. package/skills/cicd/github-flow/SKILL.md +1 -1
  51. package/skills/cicd/github-flow/release-check.mjs +3 -1
  52. package/skills/cicd/google-cloud/SKILL.md +1 -1
  53. package/skills/cicd/google-cloud/release-check.mjs +3 -1
  54. package/skills/cicd/mergify/SKILL.md +1 -1
  55. package/skills/cicd/mergify/release-check.mjs +3 -1
  56. package/skills/cicd/podman/SKILL.md +1 -1
  57. package/skills/cicd/podman/release-check.mjs +3 -1
  58. package/skills/content/article-review/SKILL.md +1 -1
  59. package/skills/content/article-review/release-check.mjs +3 -1
  60. package/skills/content/article-to-image/SKILL.md +1 -1
  61. package/skills/content/article-to-image/release-check.mjs +3 -1
  62. package/skills/content/flowchart-svg/SKILL.md +1 -1
  63. package/skills/content/flowchart-svg/release-check.mjs +3 -1
  64. package/skills/content/image-gen/SKILL.md +1 -1
  65. package/skills/content/image-gen/release-check.mjs +3 -1
  66. package/skills/content/mermaid/SKILL.md +1 -1
  67. package/skills/content/mermaid/release-check.mjs +3 -1
  68. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  69. package/skills/content/wechat-article-writer/release-check.mjs +3 -1
  70. package/skills/content/wechat-publisher/SKILL.md +1 -1
  71. package/skills/content/wechat-publisher/release-check.mjs +3 -1
  72. package/skills/content/wechat-search/SKILL.md +1 -1
  73. package/skills/content/wechat-search/release-check.mjs +3 -1
  74. package/skills/content/xai-search/SKILL.md +88 -13
  75. package/skills/content/xai-search/release-check.mjs +3 -1
  76. package/skills/content/xai-search/scripts/xai_search.sh +125 -149
  77. package/skills/core/distill-writing/SKILL.md +1 -1
  78. package/skills/core/distill-writing/release-check.mjs +3 -1
  79. package/skills/core/doc-to-md/SKILL.md +1 -1
  80. package/skills/core/doc-to-md/release-check.mjs +3 -1
  81. package/skills/core/editorial-review/SKILL.md +1 -1
  82. package/skills/core/editorial-review/release-check.mjs +3 -1
  83. package/skills/core/house-style/SKILL.md +1 -1
  84. package/skills/core/house-style/release-check.mjs +3 -1
  85. package/skills/core/plain-language/SKILL.md +1 -1
  86. package/skills/core/plain-language/release-check.mjs +3 -1
  87. package/skills/core/polish-cn/SKILL.md +1 -1
  88. package/skills/core/polish-cn/release-check.mjs +3 -1
  89. package/skills/core/reg-parser/SKILL.md +1 -1
  90. package/skills/core/reg-parser/release-check.mjs +3 -1
  91. package/skills/core/terminology/SKILL.md +1 -1
  92. package/skills/core/terminology/release-check.mjs +3 -1
  93. package/skills/core/write-doc/SKILL.md +1 -1
  94. package/skills/core/write-doc/release-check.mjs +3 -1
  95. package/skills/engineering/better-review/SKILL.md +1 -1
  96. package/skills/engineering/better-review/release-check.mjs +3 -1
  97. package/skills/engineering/contributing/SKILL.md +1 -1
  98. package/skills/engineering/contributing/release-check.mjs +3 -1
  99. package/skills/engineering/e2e-test/SKILL.md +1 -1
  100. package/skills/engineering/e2e-test/release-check.mjs +3 -1
  101. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  102. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  103. package/skills/engineering/engineering-runtime/release-check.mjs +3 -1
  104. package/skills/engineering/engineering-runtime/scripts/installation-resolver.mjs +191 -0
  105. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +51 -10
  106. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  107. package/skills/engineering/ensure-coverage/release-check.mjs +3 -1
  108. package/skills/engineering/golden-path/SKILL.md +1 -1
  109. package/skills/engineering/golden-path/release-check.mjs +3 -1
  110. package/skills/engineering/harness-runtime/SKILL.md +1 -1
  111. package/skills/engineering/harness-runtime/release-check.mjs +3 -1
  112. package/skills/engineering/resolve-issues/SKILL.md +11 -20
  113. package/skills/engineering/resolve-issues/references/delivery-progress.md +63 -0
  114. package/skills/engineering/resolve-issues/references/expire.md +24 -11
  115. package/skills/engineering/resolve-issues/references/implementation.md +9 -1
  116. package/skills/engineering/resolve-issues/references/preflight.md +7 -0
  117. package/skills/engineering/resolve-issues/references/shared-modules.md +27 -0
  118. package/skills/engineering/resolve-issues/references/task-plan.md +12 -5
  119. package/skills/engineering/resolve-issues/release-check.mjs +3 -1
  120. package/skills/engineering/resolve-issues/scripts/active-installation.mjs +32 -0
  121. package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +3 -0
  122. package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +17 -1
  123. package/skills/engineering/resolve-release/SKILL.md +1 -1
  124. package/skills/engineering/resolve-release/release-check.mjs +3 -1
  125. package/skills/engineering/rush-issues/SKILL.md +5 -2
  126. package/skills/engineering/rush-issues/release-check.mjs +3 -1
  127. package/skills/engineering/rush-release/SKILL.md +1 -1
  128. package/skills/engineering/rush-release/release-check.mjs +3 -1
  129. package/skills/engineering/test-quality/SKILL.md +1 -1
  130. package/skills/engineering/test-quality/release-check.mjs +3 -1
  131. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  132. package/skills/risk-compliance/compliance-audit/release-check.mjs +3 -1
  133. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  134. package/skills/risk-compliance/contract-compare/release-check.mjs +3 -1
  135. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  136. package/skills/risk-compliance/contract-review/release-check.mjs +3 -1
  137. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  138. package/skills/risk-compliance/doc-authenticity/release-check.mjs +3 -1
  139. package/skills/risk-compliance/fraud-analysis/SKILL.md +1 -1
  140. package/skills/risk-compliance/fraud-analysis/release-check.mjs +3 -1
  141. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  142. package/skills/risk-compliance/payment-analysis/release-check.mjs +3 -1
  143. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  144. package/skills/risk-compliance/similar-domain/release-check.mjs +3 -1
  145. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
  146. package/skills/risk-compliance/tld-detection/release-check.mjs +3 -1
  147. package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +0 -172
  148. package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +0 -36
  149. package/skills/app-dev/data-quality/scripts/data-quality.test.mjs +0 -12
  150. package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +0 -637
  151. package/skills/cicd/github-flow/scripts/flow.test.mjs +0 -114
  152. package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +0 -108
  153. package/skills/cicd/mergify/scripts/audit.test.mjs +0 -201
  154. package/skills/cicd/mergify/scripts/entrypoints.test.mjs +0 -106
  155. package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +0 -30
  156. package/skills/cicd/mergify/scripts/stack-push.test.mjs +0 -233
  157. package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +0 -1826
  158. package/skills/content/image-gen/scripts/credentials.test.mjs +0 -212
  159. package/skills/content/image-gen/scripts/options.test.mjs +0 -245
  160. package/skills/content/xai-search/tests/smoke_test.sh +0 -36
  161. package/skills/core/polish-cn/scripts/polish-cn.test.mjs +0 -244
  162. package/skills/core/reg-parser/scripts/reg-parser.test.mjs +0 -165
  163. package/skills/engineering/better-review/scripts/pr-context.test.mjs +0 -168
  164. package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +0 -587
  165. package/skills/engineering/better-review/scripts/scan-diff.test.mjs +0 -414
  166. package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +0 -96
  167. package/skills/engineering/contributing/scripts/persist-conventions.test.mjs +0 -118
  168. package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +0 -106
  169. package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +0 -117
  170. package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +0 -69
  171. package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +0 -98
  172. package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +0 -71
  173. package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +0 -59
  174. package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +0 -76
  175. package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +0 -68
  176. package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +0 -95
  177. package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +0 -288
  178. package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +0 -96
  179. package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +0 -96
  180. package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +0 -47
  181. package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +0 -86
  182. package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +0 -447
  183. package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +0 -552
  184. package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +0 -289
  185. package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +0 -119
  186. package/skills/engineering/golden-path/scripts/golden-path.test.mjs +0 -1457
  187. package/skills/engineering/harness-runtime/discover-models.test.mjs +0 -363
  188. package/skills/engineering/harness-runtime/harness-runtime.test.mjs +0 -967
  189. package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +0 -829
  190. package/skills/engineering/harness-runtime/model-catalog.test.mjs +0 -366
  191. package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +0 -280
  192. package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +0 -346
  193. package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +0 -88
  194. package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +0 -264
  195. package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +0 -79
  196. package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +0 -107
  197. package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +0 -14
  198. package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +0 -149
  199. package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +0 -915
  200. package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +0 -156
  201. package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +0 -448
  202. package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +0 -217
  203. package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +0 -91
  204. package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +0 -1060
  205. package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +0 -458
  206. package/skills/engineering/resolve-release/scripts/apply.test.mjs +0 -99
  207. package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +0 -100
  208. package/skills/engineering/resolve-release/scripts/flow.test.mjs +0 -340
  209. package/skills/engineering/resolve-release/scripts/green-head.test.mjs +0 -101
  210. package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +0 -426
  211. package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +0 -659
  212. package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +0 -317
  213. package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +0 -291
  214. package/skills/engineering/resolve-release/scripts/plan.test.mjs +0 -428
  215. package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +0 -591
  216. package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +0 -119
  217. package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +0 -104
  218. package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +0 -14
  219. package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +0 -12
  220. package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +0 -212
  221. package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +0 -14
  222. package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +0 -14
  223. package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +0 -134
  224. 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
- })