@1aboveio/skills 1.0.8 → 1.0.10

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,363 +0,0 @@
1
- // discover-models tests — real fixture config files under a temp HOME, NEVER the
2
- // user's real ~/.pi / ~/.codex / ~/.claude. Every case writes its own config tree
3
- // into a scratch dir and runs the script with `HOME=<tmp>` and an INJECTED env for
4
- // the apiKey `$VAR` resolution, so no test reads or depends on the real machine's
5
- // config or environment. A test that touched the real config would be a defect —
6
- // the whole point of this unit is a trustworthy, isolated discovery read.
7
-
8
- import { test } from 'node:test'
9
- import assert from 'node:assert/strict'
10
- import fs from 'node:fs'
11
- import os from 'node:os'
12
- import path from 'node:path'
13
- import { fileURLToPath } from 'node:url'
14
- import { execFileSync } from 'node:child_process'
15
-
16
- import { discoverPi, discoverCodex, discoverClaudeCode, apiKeyResolves } from './discover-models.mjs'
17
-
18
- const scriptPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'bin', 'discover-models.mjs')
19
-
20
- // ---- temp-HOME fixture scaffolding ----
21
-
22
- function mkHome() {
23
- return fs.mkdtempSync(path.join(os.tmpdir(), 'discover-models-'))
24
- }
25
-
26
- function writeJson(file, obj) {
27
- fs.mkdirSync(path.dirname(file), { recursive: true })
28
- fs.writeFileSync(file, JSON.stringify(obj, null, 2))
29
- }
30
-
31
- function writeText(file, text) {
32
- fs.mkdirSync(path.dirname(file), { recursive: true })
33
- fs.writeFileSync(file, text)
34
- }
35
-
36
- // Run the script with a fully-controlled env: an explicit HOME (the fixture tree)
37
- // and only the env vars a case injects — so `$VAR` resolution is tested against
38
- // injected values, never the real environment. Returns { code, stdout, json }.
39
- function run(args, { home, extraEnv = {} } = {}) {
40
- const env = { PATH: process.env.PATH, HOME: home, ...extraEnv }
41
- let stdout = ''
42
- let code = 0
43
- try {
44
- stdout = execFileSync('node', [scriptPath, ...args], { encoding: 'utf8', env })
45
- } catch (err) {
46
- code = err.status ?? 1
47
- stdout = err.stdout ?? ''
48
- }
49
- let json = null
50
- try {
51
- json = JSON.parse(stdout)
52
- } catch {
53
- /* non-JSON (help/usage) — leave json null */
54
- }
55
- return { code, stdout, json }
56
- }
57
-
58
- const ids = (json) => json.discovered.map((d) => d.id)
59
-
60
- // ---- Pi: the full credentialed-remainder fixture ----
61
-
62
- // Builds the Pi fixture the task spec asks for, under a fresh temp HOME:
63
- // - enabledModels: the curated picker set
64
- // - a default provider/model
65
- // - a models.json custom entry whose provider apiKey is a LITERAL (resolves)
66
- // - a models.json custom entry whose provider apiKey is $SET_VAR (resolves)
67
- // - a models.json custom entry whose provider apiKey is $UNSET_VAR (does NOT resolve)
68
- // - an auth.json-credentialed provider with NO enabledModels entry (provider-level)
69
- function buildPiHome() {
70
- const home = mkHome()
71
- writeJson(path.join(home, '.pi', 'agent', 'settings.json'), {
72
- defaultProvider: 'openai',
73
- defaultModel: 'gpt-x-terra',
74
- enabledModels: ['openai/gpt-x-terra', 'openai/gpt-x-sol', 'acme/curated-1'],
75
- })
76
- writeJson(path.join(home, '.pi', 'agent', 'models.json'), {
77
- providers: {
78
- // openai is curated (has enabledModels entries) — a proxy provider, no models[]
79
- openai: { baseUrl: 'https://example/v1', apiKey: '$OPENAI_KEY' },
80
- // literal apiKey → resolves; custom models emitted at model level
81
- litprov: { apiKey: 'sk-literal-abc', models: [{ id: 'lit-model-1' }, { id: 'lit-model-2' }] },
82
- // $SET_VAR apiKey → resolves (env injected)
83
- setprov: { apiKey: '$SET_VAR', models: [{ id: 'set-model-1' }] },
84
- // $UNSET_VAR apiKey → does NOT resolve; its custom model is a KNOWN definition
85
- // the user cannot run — the never-a-source / credential-gate case.
86
- unsetprov: { apiKey: '$UNSET_VAR', models: [{ id: 'unset-model-1' }] },
87
- },
88
- })
89
- // A provider credentialed via auth.json with no enabledModels entry and no
90
- // models[] detail — listed at PROVIDER level only.
91
- writeJson(path.join(home, '.pi', 'agent', 'auth.json'), {
92
- google: { type: 'apiKey', key: 'stored-google-key' },
93
- })
94
- return home
95
- }
96
-
97
- // @covers package:harness-runtime
98
- // @level integration
99
- test('pi: discovers enabledModels, the default, and credentialed custom models', () => {
100
- const home = buildPiHome()
101
- const { code, json } = run(['--harness', 'pi'], { home, extraEnv: { OPENAI_KEY: 'x', SET_VAR: 'yes' } })
102
- assert.equal(code, 0)
103
- assert.equal(json.harness, 'pi')
104
- assert.equal(json.completeness, 'full')
105
- const discovered = ids(json)
106
- // curated picker set
107
- assert.ok(discovered.includes('openai/gpt-x-terra'))
108
- assert.ok(discovered.includes('openai/gpt-x-sol'))
109
- assert.ok(discovered.includes('acme/curated-1'))
110
- // literal-apiKey custom models
111
- assert.ok(discovered.includes('litprov/lit-model-1'))
112
- assert.ok(discovered.includes('litprov/lit-model-2'))
113
- // $SET_VAR-apiKey custom model
114
- assert.ok(discovered.includes('setprov/set-model-1'))
115
- })
116
-
117
- test('pi: the default provider/model is present and sourced as the default', () => {
118
- const home = buildPiHome()
119
- const { json } = run(['--harness', 'pi'], { home, extraEnv: { OPENAI_KEY: 'x', SET_VAR: 'yes' } })
120
- const entry = json.discovered.find((d) => d.id === 'openai/gpt-x-terra')
121
- assert.ok(entry, 'default model must be discovered')
122
- // It is already in enabledModels, so first-source-wins keeps the enabledModels source.
123
- assert.equal(entry.source, 'settings.json:enabledModels')
124
- })
125
-
126
- test('pi: an auth.json-credentialed provider with no enabledModels entry is listed at PROVIDER level only', () => {
127
- const home = buildPiHome()
128
- const { json } = run(['--harness', 'pi'], { home, extraEnv: { OPENAI_KEY: 'x', SET_VAR: 'yes' } })
129
- const discovered = ids(json)
130
- assert.ok(discovered.includes('google/*'), 'expected provider-level google/*')
131
- // NEVER an expanded per-model registry for the credentialed-but-uncurated provider.
132
- assert.ok(!discovered.some((id) => id.startsWith('google/') && id !== 'google/*'),
133
- 'google must appear only at provider level, never expanded into concrete model ids')
134
- const entry = json.discovered.find((d) => d.id === 'google/*')
135
- assert.match(entry.source, /auth\.json entry/)
136
- })
137
-
138
- test('pi: NEVER-A-SOURCE — a config-known model whose provider key does not resolve is NOT emitted', () => {
139
- const home = buildPiHome()
140
- // $UNSET_VAR is deliberately absent from the injected env.
141
- const { json } = run(['--harness', 'pi'], { home, extraEnv: { OPENAI_KEY: 'x', SET_VAR: 'yes' } })
142
- const discovered = ids(json)
143
- assert.ok(
144
- !discovered.includes('unsetprov/unset-model-1'),
145
- 'a custom model whose provider apiKey ($UNSET_VAR) does not resolve must NOT be discovered — ' +
146
- 'it is a definition the config knows but the user cannot run',
147
- )
148
- // And the provider itself is not credentialed, so no provider-level entry either.
149
- assert.ok(!discovered.includes('unsetprov/*'))
150
- })
151
-
152
- test('pi: records the never-a-source rule as a note', () => {
153
- const home = buildPiHome()
154
- const { json } = run(['--harness', 'pi'], { home, extraEnv: { OPENAI_KEY: 'x', SET_VAR: 'yes' } })
155
- assert.ok(json.notes.some((n) => /never a discovery source/.test(n) && /pi --models/.test(n)))
156
- })
157
-
158
- test('pi: missing config is graceful — empty set + note, exit 0, no crash', () => {
159
- const home = mkHome() // no .pi tree at all
160
- const { code, json } = run(['--harness', 'pi'], { home })
161
- assert.equal(code, 0)
162
- assert.equal(json.completeness, 'full')
163
- assert.deepEqual(json.discovered, [])
164
- assert.ok(json.notes.some((n) => /not found/.test(n)))
165
- })
166
-
167
- // ---- Codex ----
168
-
169
- // @covers package:harness-runtime
170
- // @level integration
171
- test('codex: discovers configured defaults without claiming a complete runnable inventory', () => {
172
- const home = mkHome()
173
- writeText(path.join(home, '.codex', 'config.toml'),
174
- 'model = "gpt-x-sol"\n' +
175
- 'model_reasoning_effort = "high"\n' + // must NOT be read as a model
176
- 'model_context_window = 1000000\n' +
177
- '\n' +
178
- '[profiles.deep]\n' +
179
- 'model = "gpt-x-max"\n')
180
- const { code, json } = run(['--harness', 'codex'], { home })
181
- assert.equal(code, 0)
182
- assert.equal(json.harness, 'codex')
183
- assert.equal(json.completeness, 'partial')
184
- const discovered = ids(json)
185
- assert.deepEqual(discovered.sort(), ['gpt-x-max', 'gpt-x-sol'].sort())
186
- // The `model_*` keys must not leak in as models.
187
- assert.ok(!discovered.includes('high'))
188
- assert.ok(!discovered.some((id) => /^\d+$/.test(id)))
189
- // The top-level model is sourced as config.toml:model; the profile one carries its table.
190
- assert.equal(json.discovered.find((d) => d.id === 'gpt-x-sol').source, 'config.toml:model')
191
- assert.match(json.discovered.find((d) => d.id === 'gpt-x-max').source, /\[profiles\.deep\]/)
192
- assert.ok(json.notes.some((note) => /partial/.test(note)))
193
- })
194
-
195
- test('codex: current-turn advertised ids are preserved, unioned, and make discovery full', () => {
196
- const home = mkHome()
197
- writeText(path.join(home, '.codex', 'config.toml'), 'model = "configured-default"\n')
198
- const { code, json } = run([
199
- '--harness', 'codex',
200
- '--available', 'advertised/model-a,configured-default,advertised:model-b',
201
- ], { home })
202
-
203
- assert.equal(code, 0)
204
- assert.equal(json.completeness, 'full')
205
- assert.deepEqual(ids(json), ['advertised/model-a', 'configured-default', 'advertised:model-b'])
206
- assert.equal(json.discovered[0].source, 'current-turn')
207
- assert.equal(json.discovered[2].source, 'current-turn')
208
- })
209
-
210
- test('codex: a human-named runnable id is evidence but does not turn partial discovery into full', () => {
211
- const home = mkHome()
212
- const { code, json } = run([
213
- '--harness', 'codex',
214
- '--human-named', 'operator/model-exact',
215
- ], { home })
216
-
217
- assert.equal(code, 0)
218
- assert.equal(json.completeness, 'partial')
219
- assert.deepEqual(json.discovered, [{ id: 'operator/model-exact', source: 'human-named' }])
220
- })
221
-
222
- test('codex: missing config is graceful — empty set + note, exit 0', () => {
223
- const home = mkHome()
224
- const { code, json } = run(['--harness', 'codex'], { home })
225
- assert.equal(code, 0)
226
- assert.equal(json.completeness, 'partial')
227
- assert.deepEqual(json.discovered, [])
228
- assert.ok(json.notes.some((n) => /not found/.test(n)))
229
- })
230
-
231
- // ---- Claude Code (honest-partial) ----
232
-
233
- // @covers package:harness-runtime
234
- // @level integration
235
- test('claude-code: is honest-partial — records that discovery stays manual and does NOT read the banked catalog', () => {
236
- const home = mkHome()
237
- writeJson(path.join(home, '.claude', 'settings.json'), { effortLevel: 'high', permissions: {} })
238
- // A banked catalog is present — it must NOT be treated as an availability source.
239
- writeJson(path.join(home, '.claude', 'model-catalog.json'), {
240
- harness: 'claude-code',
241
- models: [{ id: 'should-not-appear', tiers: { high: 'frontier' } }],
242
- })
243
- const { code, json } = run(['--harness', 'claude-code'], { home })
244
- assert.equal(code, 0)
245
- assert.equal(json.harness, 'claude-code')
246
- assert.equal(json.completeness, 'partial')
247
- assert.ok(!ids(json).includes('should-not-appear'),
248
- 'the banked model-catalog.json is a cache of confirmations, never an availability source')
249
- assert.ok(json.notes.some((n) => /Agent-tool model enum/.test(n) && /stays manual/.test(n)))
250
- })
251
-
252
- test('claude-code: current-turn advertised ids complete discovery and union with settings', () => {
253
- const home = mkHome()
254
- writeJson(path.join(home, '.claude', 'settings.json'), { model: 'configured-model' })
255
- const { code, json } = run([
256
- '--harness', 'claude-code',
257
- '--available', 'advertised-model,configured-model',
258
- ], { home })
259
-
260
- assert.equal(code, 0)
261
- assert.equal(json.completeness, 'full')
262
- assert.deepEqual(ids(json), ['advertised-model', 'configured-model'])
263
- assert.ok(json.discovered.every((model) => model.source === 'current-turn'))
264
- })
265
-
266
- // ---- CLI contract: help, unknown flags, auto-detect ----
267
-
268
- test('--help exits 0 with non-empty usage naming the flags and exit codes', () => {
269
- const { code, stdout } = run(['--help'], { home: mkHome() })
270
- assert.equal(code, 0)
271
- assert.ok(stdout.includes('--harness'))
272
- assert.ok(stdout.includes('--available'))
273
- assert.ok(stdout.includes('--human-named'))
274
- assert.ok(stdout.includes('Exit codes'))
275
- assert.ok(/pi\|codex\|claude-code/.test(stdout))
276
- })
277
-
278
- test('-h is an alias for --help (exit 0)', () => {
279
- const { code, stdout } = run(['-h'], { home: mkHome() })
280
- assert.equal(code, 0)
281
- assert.ok(stdout.length > 0)
282
- })
283
-
284
- test('an unknown flag exits 2 with usage', () => {
285
- const { code } = run(['--bogus'], { home: mkHome() })
286
- assert.equal(code, 2)
287
- })
288
-
289
- test('an unknown --harness value exits 2', () => {
290
- const { code } = run(['--harness', 'nope'], { home: mkHome() })
291
- assert.equal(code, 2)
292
- })
293
-
294
- test('no --harness with an ambiguous/empty HOME exits 2 (never guesses)', () => {
295
- const { code } = run([], { home: mkHome() }) // empty HOME: no harness present
296
- assert.equal(code, 2)
297
- })
298
-
299
- test('no --harness auto-detects the sole present harness', () => {
300
- const home = mkHome()
301
- writeText(path.join(home, '.codex', 'config.toml'), 'model = "solo-model"\n')
302
- const { code, json } = run([], { home })
303
- assert.equal(code, 0)
304
- assert.equal(json.harness, 'codex')
305
- assert.ok(ids(json).includes('solo-model'))
306
- })
307
-
308
- // ---- pure-core unit checks (fast, no spawn) ----
309
-
310
- test('apiKeyResolves: literal resolves; $SET resolves; $UNSET does not; empty does not', () => {
311
- assert.equal(apiKeyResolves('sk-abc', {}).resolved, true)
312
- assert.equal(apiKeyResolves('$K', { K: 'v' }).resolved, true)
313
- assert.equal(apiKeyResolves('$K', {}).resolved, false)
314
- assert.equal(apiKeyResolves('', {}).resolved, false)
315
- assert.equal(apiKeyResolves(undefined, {}).resolved, false)
316
- })
317
-
318
- test('discoverPi (pure): credential gate excludes the unresolved custom model', () => {
319
- const { discovered } = discoverPi({
320
- settings: { enabledModels: ['a/one'] },
321
- models: {
322
- providers: {
323
- ok: { apiKey: 'lit', models: [{ id: 'runnable' }] },
324
- no: { apiKey: '$MISSING', models: [{ id: 'notrunnable' }] },
325
- },
326
- },
327
- auth: {},
328
- env: {},
329
- })
330
- const set = discovered.map((d) => d.id)
331
- assert.ok(set.includes('a/one'))
332
- assert.ok(set.includes('ok/runnable'))
333
- assert.ok(!set.includes('no/notrunnable'))
334
- })
335
-
336
- // @covers package:harness-runtime
337
- // @level unit
338
- test('discoverCodex (pure): explicit current-turn ids pass unchanged and take source precedence', () => {
339
- const advertised = ['provider/model-a', 'model:b']
340
- const { discovered, completeness } = discoverCodex({
341
- configText: 'model = "provider/model-a"\nmodel = "config-only"\n',
342
- spawnModelIds: advertised,
343
- })
344
- assert.equal(completeness, 'full')
345
- assert.deepEqual(discovered, [
346
- { id: 'provider/model-a', source: 'current-turn' },
347
- { id: 'model:b', source: 'current-turn' },
348
- { id: 'config-only', source: 'config.toml:model' },
349
- ])
350
- assert.deepEqual(advertised, ['provider/model-a', 'model:b'])
351
- })
352
-
353
- test('discoverCodex (pure): empty text yields empty + note, not a throw', () => {
354
- const { discovered, notes, completeness } = discoverCodex({ configText: null })
355
- assert.deepEqual(discovered, [])
356
- assert.equal(completeness, 'partial')
357
- assert.ok(notes.length > 0)
358
- })
359
-
360
- test('discoverClaudeCode (pure): always carries the honest-manual note', () => {
361
- const { notes } = discoverClaudeCode({ settings: {} })
362
- assert.ok(notes.some((n) => /stays manual/.test(n)))
363
- })