@t275005746/gse 0.1.0 → 0.1.2

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 (228) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +42 -42
  2. package/.github/ISSUE_TEMPLATE/change_request.yml +50 -50
  3. package/.github/ISSUE_TEMPLATE/config.yml +5 -5
  4. package/.github/PULL_REQUEST_TEMPLATE.md +38 -38
  5. package/.github/workflows/validate-gse.yml +33 -33
  6. package/.gse/README.md +18 -18
  7. package/.gse/gse-development-protocol.md +50 -50
  8. package/.gse/project-profile.md +29 -29
  9. package/.gse/quality-gates.md +25 -25
  10. package/.gse/releases/public-registry-publication-npm.md +49 -0
  11. package/.gse/releases/public-release-owner-required.md +65 -65
  12. package/.gse/releases/public-security-contact-owner-required.md +45 -45
  13. package/.gse/state.json +147 -27
  14. package/CHANGELOG.md +31 -15
  15. package/CONTRIBUTING.md +64 -64
  16. package/LICENSE +21 -21
  17. package/README.md +14 -7
  18. package/README.zh-CN.md +14 -7
  19. package/SECURITY.md +41 -41
  20. package/SKILL.md +32 -12
  21. package/SUPPORT.md +38 -38
  22. package/assets/marketplace/README.md +7 -7
  23. package/assets/marketplace/gse-listing.json +75 -75
  24. package/assets/templates/acceptance-execution-packet.md +73 -73
  25. package/assets/templates/adr.md +14 -14
  26. package/assets/templates/change-brief.md +16 -16
  27. package/assets/templates/design.md +18 -18
  28. package/assets/templates/dispatch-packet.md +100 -92
  29. package/assets/templates/evidence.md +15 -9
  30. package/assets/templates/execution-quality-pack.md +65 -65
  31. package/assets/templates/goal-map.md +21 -21
  32. package/assets/templates/host-adapter.md +48 -48
  33. package/assets/templates/host-ui-invocation-record.md +42 -42
  34. package/assets/templates/incident-review.md +60 -60
  35. package/assets/templates/public-channel-publication-record.md +49 -49
  36. package/assets/templates/public-ci-run-record.md +53 -53
  37. package/assets/templates/public-release-record.md +65 -65
  38. package/assets/templates/public-repository-settings-record.md +59 -59
  39. package/assets/templates/public-security-contact-record.md +45 -45
  40. package/assets/templates/release-trust-record.md +32 -32
  41. package/assets/templates/review.md +18 -18
  42. package/assets/templates/role-fallback-packet.md +49 -0
  43. package/assets/templates/spec.md +16 -16
  44. package/assets/templates/target-adoption-evidence.md +29 -29
  45. package/assets/templates/tasks.md +17 -17
  46. package/assets/templates/update-release-acceptance-record.md +58 -58
  47. package/examples/README.md +22 -22
  48. package/examples/agent-runtime-host/.claude/gse-adapter.md +6 -6
  49. package/examples/agent-runtime-host/.codex/gse-adapter.md +7 -7
  50. package/examples/agent-runtime-host/.gse/goal-map.md +7 -7
  51. package/examples/agent-runtime-host/.gse/project-profile.md +27 -27
  52. package/examples/agent-runtime-host/.gse/tooling.md +5 -5
  53. package/examples/agent-runtime-host/.mcp.json +9 -9
  54. package/examples/agent-runtime-host/AGENTS.md +5 -5
  55. package/examples/agent-runtime-host/README.md +10 -10
  56. package/examples/agent-runtime-host/docs/model-routing.md +5 -5
  57. package/examples/cli-tool/.gse/project-profile.md +21 -21
  58. package/examples/cli-tool/AGENTS.md +5 -5
  59. package/examples/cli-tool/README.md +12 -12
  60. package/examples/cli-tool/package.json +21 -21
  61. package/examples/small-app/.env.example +2 -2
  62. package/examples/small-app/.github/workflows/ci.yml +8 -8
  63. package/examples/small-app/AGENTS.md +5 -5
  64. package/examples/small-app/README.md +12 -12
  65. package/examples/small-app/package.json +26 -26
  66. package/examples/small-app/playwright.config.ts +4 -4
  67. package/package.json +52 -44
  68. package/references/adoption-recipes.md +171 -171
  69. package/references/agent-roles.md +42 -21
  70. package/references/architecture-health.md +101 -101
  71. package/references/benchmark-audit.md +73 -73
  72. package/references/commands.md +74 -45
  73. package/references/community-channels.md +46 -46
  74. package/references/compatibility.md +70 -70
  75. package/references/design-basis.md +38 -38
  76. package/references/domain-model.md +129 -129
  77. package/references/domain-quality-gates.md +75 -75
  78. package/references/drift-audit.md +81 -80
  79. package/references/evidence-taxonomy.md +145 -108
  80. package/references/file-ownership.md +97 -93
  81. package/references/final-form-roadmap.md +201 -0
  82. package/references/final-readiness.md +84 -84
  83. package/references/forward-test.md +133 -133
  84. package/references/goal-map.md +36 -36
  85. package/references/host-adapters.md +129 -101
  86. package/references/learning-system.md +42 -26
  87. package/references/maintenance-cadence.md +51 -0
  88. package/references/marketplace-discovery.md +46 -46
  89. package/references/model-routing.md +103 -103
  90. package/references/open-source-defaults.md +39 -39
  91. package/references/operating-model.md +52 -52
  92. package/references/packaging.md +277 -277
  93. package/references/project-agent-workspace.md +89 -89
  94. package/references/project-bootstrap.md +122 -122
  95. package/references/project-guards.md +52 -0
  96. package/references/project-profile.md +57 -57
  97. package/references/public-release.md +174 -174
  98. package/references/quality-gates.md +96 -89
  99. package/references/recovery.md +176 -176
  100. package/references/release-trust.md +43 -43
  101. package/references/release.md +126 -126
  102. package/references/review.md +141 -141
  103. package/references/role-dispatch-fallback.md +54 -0
  104. package/references/router.md +90 -90
  105. package/references/spec-workflow.md +66 -66
  106. package/references/task-levels.md +81 -81
  107. package/references/tool-adapters.md +80 -70
  108. package/scripts/audit-acceptance-execution-packet.mjs +133 -133
  109. package/scripts/audit-adoption-recipes.mjs +99 -99
  110. package/scripts/audit-change-lifecycle.mjs +77 -77
  111. package/scripts/audit-change-system.mjs +134 -134
  112. package/scripts/audit-ci-readiness.mjs +107 -107
  113. package/scripts/audit-close-gate-hardening.mjs +188 -0
  114. package/scripts/audit-close-gate.mjs +448 -262
  115. package/scripts/audit-command-adapters.mjs +91 -91
  116. package/scripts/audit-command-execution.mjs +212 -199
  117. package/scripts/audit-commands.mjs +7 -5
  118. package/scripts/audit-compatibility.mjs +149 -149
  119. package/scripts/audit-completion-plan-drill.mjs +230 -0
  120. package/scripts/audit-completion-readiness.mjs +290 -287
  121. package/scripts/audit-continue-preflight.mjs +234 -0
  122. package/scripts/audit-distribution.mjs +251 -251
  123. package/scripts/audit-domain-quality-gates.mjs +108 -108
  124. package/scripts/audit-evidence-levels.mjs +217 -0
  125. package/scripts/audit-evidence-placeholders.mjs +126 -126
  126. package/scripts/audit-evidence-review-queue.mjs +206 -0
  127. package/scripts/audit-final-acceptance-packet.mjs +9 -9
  128. package/scripts/audit-final-form-progress-report.mjs +19 -18
  129. package/scripts/audit-final-form-roadmap.mjs +157 -0
  130. package/scripts/audit-final-form-stale-copy.mjs +2 -2
  131. package/scripts/audit-final-readiness-promotion.mjs +255 -255
  132. package/scripts/audit-final-readiness.mjs +226 -226
  133. package/scripts/audit-fixtures.mjs +154 -154
  134. package/scripts/audit-fresh-session-readiness.mjs +177 -177
  135. package/scripts/audit-host-capabilities.mjs +237 -0
  136. package/scripts/audit-host-runtime-evidence-handoff.mjs +159 -159
  137. package/scripts/audit-host-runtime-invocation-drill.mjs +240 -240
  138. package/scripts/audit-host-runtime-invocations.mjs +254 -254
  139. package/scripts/audit-host-ui-invocation.mjs +132 -132
  140. package/scripts/audit-installed-sync.mjs +203 -0
  141. package/scripts/audit-learning-drift.mjs +292 -0
  142. package/scripts/audit-learning-promotion.mjs +351 -0
  143. package/scripts/audit-learning-system.mjs +24 -14
  144. package/scripts/audit-local-final-form-completion.mjs +11 -10
  145. package/scripts/audit-maintenance-cadence.mjs +139 -0
  146. package/scripts/audit-maintenance-snapshot.mjs +181 -0
  147. package/scripts/audit-marketplace-discovery.mjs +122 -122
  148. package/scripts/audit-npm-package-metadata.mjs +160 -154
  149. package/scripts/audit-npm-publish-dry-run.mjs +194 -166
  150. package/scripts/audit-npm-tarball-install.mjs +195 -189
  151. package/scripts/audit-open-source-defaults.mjs +92 -92
  152. package/scripts/audit-open-source-readiness.mjs +97 -97
  153. package/scripts/audit-owner-external-gate-kit.mjs +12 -11
  154. package/scripts/audit-project-guards.mjs +189 -0
  155. package/scripts/audit-project.mjs +144 -141
  156. package/scripts/audit-public-acceptance-command-dry-run-drill.mjs +203 -203
  157. package/scripts/audit-public-acceptance-handoff.mjs +10 -10
  158. package/scripts/audit-public-acceptance-readiness.mjs +222 -222
  159. package/scripts/audit-public-channel-publication.mjs +248 -248
  160. package/scripts/audit-public-ci-run.mjs +184 -184
  161. package/scripts/audit-public-collaboration-templates.mjs +98 -98
  162. package/scripts/audit-public-external-gate-probe.mjs +206 -206
  163. package/scripts/audit-public-release-checklist.mjs +17 -15
  164. package/scripts/audit-public-release-decision.mjs +201 -201
  165. package/scripts/audit-public-release-metadata.mjs +176 -176
  166. package/scripts/audit-public-repository-settings.mjs +237 -237
  167. package/scripts/audit-public-security-contact.mjs +171 -171
  168. package/scripts/audit-readme-docs.mjs +6 -4
  169. package/scripts/audit-recovery-readiness.mjs +98 -98
  170. package/scripts/audit-release-bundle.mjs +13 -11
  171. package/scripts/audit-release-owner-action-plan-drill.mjs +5 -4
  172. package/scripts/audit-release-owner-action-plan.mjs +10 -10
  173. package/scripts/audit-release-readiness.mjs +106 -106
  174. package/scripts/audit-release-status-manifest.mjs +4 -4
  175. package/scripts/audit-release-trust.mjs +62 -62
  176. package/scripts/audit-remote-distribution.mjs +266 -266
  177. package/scripts/audit-roadmap-consistency.mjs +234 -230
  178. package/scripts/audit-role-dispatch-fallback.mjs +212 -0
  179. package/scripts/audit-session-sync.mjs +127 -0
  180. package/scripts/audit-signing.mjs +147 -147
  181. package/scripts/audit-state-freshness.mjs +20 -14
  182. package/scripts/audit-state-repair.mjs +360 -0
  183. package/scripts/audit-target-adoption-evidence.mjs +117 -117
  184. package/scripts/audit-target-hardening-drills.mjs +267 -0
  185. package/scripts/audit-target-project.mjs +507 -507
  186. package/scripts/audit-tool-fallback-policy.mjs +180 -0
  187. package/scripts/audit-ui-browser-evidence-policy.mjs +191 -0
  188. package/scripts/audit-update-release-acceptance.mjs +136 -136
  189. package/scripts/audit-v1-target-validation.mjs +269 -269
  190. package/scripts/audit-validation-profiles.mjs +125 -123
  191. package/scripts/backfill-evidence-levels.mjs +98 -0
  192. package/scripts/check-encoding.mjs +72 -0
  193. package/scripts/close-change.mjs +116 -116
  194. package/scripts/discover-project-profile.mjs +307 -307
  195. package/scripts/generate-command-adapter.mjs +231 -231
  196. package/scripts/generate-continue-packet.mjs +1214 -0
  197. package/scripts/generate-final-acceptance-packet.mjs +188 -173
  198. package/scripts/generate-final-form-progress-report.mjs +191 -189
  199. package/scripts/generate-host-runtime-evidence-handoff.mjs +198 -191
  200. package/scripts/generate-maintenance-snapshot.mjs +216 -0
  201. package/scripts/generate-owner-external-gate-kit.mjs +295 -295
  202. package/scripts/generate-public-acceptance-handoff.mjs +168 -156
  203. package/scripts/generate-public-release-checklist.mjs +207 -207
  204. package/scripts/generate-release-bundle.mjs +505 -505
  205. package/scripts/generate-release-owner-action-plan.mjs +172 -171
  206. package/scripts/generate-release-status-manifest.mjs +199 -198
  207. package/scripts/generate-session-prompt.mjs +188 -188
  208. package/scripts/gse.mjs +67 -67
  209. package/scripts/init-change.mjs +265 -265
  210. package/scripts/init-project.mjs +793 -712
  211. package/scripts/install-gse.mjs +234 -234
  212. package/scripts/lib/evidence-placeholders.mjs +28 -28
  213. package/scripts/package-gse.mjs +174 -174
  214. package/scripts/probe-public-external-gates.mjs +167 -167
  215. package/scripts/record-host-invocation.mjs +151 -151
  216. package/scripts/record-learning.mjs +37 -8
  217. package/scripts/record-public-channel-publication.mjs +178 -178
  218. package/scripts/record-public-ci-run.mjs +180 -180
  219. package/scripts/record-public-release.mjs +175 -175
  220. package/scripts/record-public-repository-settings.mjs +209 -209
  221. package/scripts/record-public-security-contact.mjs +157 -157
  222. package/scripts/record-session-sync.mjs +87 -0
  223. package/scripts/run-gse-command.mjs +79 -47
  224. package/scripts/run-validation-profile.mjs +24 -5
  225. package/scripts/sign-gse-package.mjs +83 -83
  226. package/scripts/update-project-state.mjs +223 -223
  227. package/scripts/validate-gse.mjs +216 -0
  228. package/scripts/verify-gse-package.mjs +85 -85
@@ -1,108 +1,108 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs'
3
- import path from 'node:path'
4
-
5
- const args = process.argv.slice(2)
6
-
7
- function readArg(name, fallback = null) {
8
- const index = args.indexOf(name)
9
- if (index === -1) return fallback
10
- return args[index + 1] ?? fallback
11
- }
12
-
13
- const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
14
- const jsonOnly = args.includes('--json')
15
-
16
- function read(relativePath) {
17
- const fullPath = path.join(root, relativePath)
18
- return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8') : ''
19
- }
20
-
21
- function exists(relativePath) {
22
- return fs.existsSync(path.join(root, relativePath))
23
- }
24
-
25
- function check(id, label, ok, evidence, risk = '') {
26
- return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
27
- }
28
-
29
- const domain = read('references/domain-quality-gates.md')
30
- const quality = read('references/quality-gates.md')
31
- const review = read('references/review.md')
32
- const architecture = read('references/architecture-health.md')
33
- const skill = read('SKILL.md')
34
-
35
- const domains = [
36
- 'Security/privacy',
37
- 'Performance/cost',
38
- 'Accessibility',
39
- 'Resilience/recovery',
40
- 'UI/browser',
41
- 'API/state',
42
- 'Data/migration',
43
- 'Model/tool routing',
44
- 'Release/operations',
45
- ]
46
- const evidenceTerms = ['File inspection', 'Focused tests', 'API smokes', 'Browser smokes', 'Architecture/review scans']
47
- const outputFields = ['Domain gates selected:', 'Why selected:', 'Evidence run:', 'Evidence status:', 'Unverified tools:', 'Residual risk:', 'Next action:']
48
- const scaleTerms = ['Lite', 'Standard', 'Enterprise']
49
-
50
- const checks = [
51
- check('DQ01', 'domain quality gates reference exists', exists('references/domain-quality-gates.md'), 'references/domain-quality-gates.md'),
52
- check('DQ02', 'SKILL routes domain quality gates', skill.includes('references/domain-quality-gates.md'), 'SKILL.md Reference Routing'),
53
- check('DQ03', 'quality-gates routes to domain gates', quality.includes('references/domain-quality-gates.md') && quality.includes('## Domain Gates'), 'references/quality-gates.md'),
54
- check('DQ04', 'review protocol routes to domain gates', review.includes('references/domain-quality-gates.md'), 'references/review.md'),
55
- check('DQ05', 'all required domains are represented', domains.every((item) => domain.includes(item)), domains.join(', ')),
56
- check('DQ06', 'scale adaptation is explicit', scaleTerms.every((item) => domain.includes(item)) && domain.includes('Lite work should not inherit every gate by default'), 'Lite, Standard, Enterprise'),
57
- check('DQ07', 'evidence taxonomy routing is explicit', domain.includes('references/evidence-taxonomy.md') && domain.includes('result') && domain.includes('verified') && domain.includes('accepted'), 'evidence taxonomy labels'),
58
- check('DQ08', 'tool execution is not faked', domain.includes('Do not claim scan, benchmark, browser, accessibility, security, or resilience results unless') && domain.includes('actually executed'), 'tool execution claim rule'),
59
- check('DQ09', 'minimum evidence mapping covers major evidence modes', evidenceTerms.every((item) => domain.includes(item)), evidenceTerms.join(', ')),
60
- check('DQ10', 'output format includes selected gates and residual risk', outputFields.every((item) => domain.includes(item)), outputFields.join(', ')),
61
- check('DQ11', 'architecture health covers performance and resilience risk', architecture.includes('Performance And Resilience') && architecture.includes('migration') && architecture.includes('release'), 'references/architecture-health.md'),
62
- check('DQ12', 'quality gates remain risk-based instead of mandatory for every task', domain.includes('Pick only the gates that match the changed behavior and project risk') && quality.includes('Do not force all gates onto Lite tasks'), 'risk-based gate language'),
63
- ]
64
-
65
- const passed = checks.filter((item) => item.status === 'passed').length
66
- const failed = checks.length - passed
67
- const report = {
68
- root,
69
- generatedAt: new Date().toISOString(),
70
- summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
71
- workflows: { domainQualityGates: failed === 0 ? 'verified' : 'failed' },
72
- limits: [
73
- 'Domain quality gate audit verifies reusable guidance and routing; it does not run project-specific security scans, benchmarks, accessibility tools, browser tests, or API smokes.',
74
- 'Projects must still execute the selected gates with their own commands, tools, owners, and evidence.',
75
- ],
76
- checks,
77
- }
78
-
79
- function renderMarkdown(data) {
80
- const lines = []
81
- lines.push('# GSE Domain Quality Gate Audit')
82
- lines.push('')
83
- lines.push('Generated: ' + data.generatedAt)
84
- lines.push('Root: ' + data.root)
85
- lines.push('')
86
- lines.push('## Summary')
87
- lines.push('')
88
- lines.push('- Status: ' + data.summary.status)
89
- lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
90
- lines.push('- Domain quality gates: ' + data.workflows.domainQualityGates)
91
- lines.push('')
92
- lines.push('## Checks')
93
- lines.push('')
94
- for (const item of data.checks) {
95
- const marker = item.status === 'passed' ? '[x]' : '[ ]'
96
- lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
97
- }
98
- lines.push('')
99
- lines.push('## Limits')
100
- lines.push('')
101
- for (const item of data.limits) lines.push('- ' + item)
102
- return lines.join('\n') + '\n'
103
- }
104
-
105
- if (jsonOnly) console.log(JSON.stringify(report, null, 2))
106
- else console.log(renderMarkdown(report))
107
-
108
- if (failed > 0) process.exit(1)
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+
5
+ const args = process.argv.slice(2)
6
+
7
+ function readArg(name, fallback = null) {
8
+ const index = args.indexOf(name)
9
+ if (index === -1) return fallback
10
+ return args[index + 1] ?? fallback
11
+ }
12
+
13
+ const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
14
+ const jsonOnly = args.includes('--json')
15
+
16
+ function read(relativePath) {
17
+ const fullPath = path.join(root, relativePath)
18
+ return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8') : ''
19
+ }
20
+
21
+ function exists(relativePath) {
22
+ return fs.existsSync(path.join(root, relativePath))
23
+ }
24
+
25
+ function check(id, label, ok, evidence, risk = '') {
26
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
27
+ }
28
+
29
+ const domain = read('references/domain-quality-gates.md')
30
+ const quality = read('references/quality-gates.md')
31
+ const review = read('references/review.md')
32
+ const architecture = read('references/architecture-health.md')
33
+ const skill = read('SKILL.md')
34
+
35
+ const domains = [
36
+ 'Security/privacy',
37
+ 'Performance/cost',
38
+ 'Accessibility',
39
+ 'Resilience/recovery',
40
+ 'UI/browser',
41
+ 'API/state',
42
+ 'Data/migration',
43
+ 'Model/tool routing',
44
+ 'Release/operations',
45
+ ]
46
+ const evidenceTerms = ['File inspection', 'Focused tests', 'API smokes', 'Browser smokes', 'Architecture/review scans']
47
+ const outputFields = ['Domain gates selected:', 'Why selected:', 'Evidence run:', 'Evidence status:', 'Unverified tools:', 'Residual risk:', 'Next action:']
48
+ const scaleTerms = ['Lite', 'Standard', 'Enterprise']
49
+
50
+ const checks = [
51
+ check('DQ01', 'domain quality gates reference exists', exists('references/domain-quality-gates.md'), 'references/domain-quality-gates.md'),
52
+ check('DQ02', 'SKILL routes domain quality gates', skill.includes('references/domain-quality-gates.md'), 'SKILL.md Reference Routing'),
53
+ check('DQ03', 'quality-gates routes to domain gates', quality.includes('references/domain-quality-gates.md') && quality.includes('## Domain Gates'), 'references/quality-gates.md'),
54
+ check('DQ04', 'review protocol routes to domain gates', review.includes('references/domain-quality-gates.md'), 'references/review.md'),
55
+ check('DQ05', 'all required domains are represented', domains.every((item) => domain.includes(item)), domains.join(', ')),
56
+ check('DQ06', 'scale adaptation is explicit', scaleTerms.every((item) => domain.includes(item)) && domain.includes('Lite work should not inherit every gate by default'), 'Lite, Standard, Enterprise'),
57
+ check('DQ07', 'evidence taxonomy routing is explicit', domain.includes('references/evidence-taxonomy.md') && domain.includes('result') && domain.includes('verified') && domain.includes('accepted'), 'evidence taxonomy labels'),
58
+ check('DQ08', 'tool execution is not faked', domain.includes('Do not claim scan, benchmark, browser, accessibility, security, or resilience results unless') && domain.includes('actually executed'), 'tool execution claim rule'),
59
+ check('DQ09', 'minimum evidence mapping covers major evidence modes', evidenceTerms.every((item) => domain.includes(item)), evidenceTerms.join(', ')),
60
+ check('DQ10', 'output format includes selected gates and residual risk', outputFields.every((item) => domain.includes(item)), outputFields.join(', ')),
61
+ check('DQ11', 'architecture health covers performance and resilience risk', architecture.includes('Performance And Resilience') && architecture.includes('migration') && architecture.includes('release'), 'references/architecture-health.md'),
62
+ check('DQ12', 'quality gates remain risk-based instead of mandatory for every task', domain.includes('Pick only the gates that match the changed behavior and project risk') && quality.includes('Do not force all gates onto Lite tasks'), 'risk-based gate language'),
63
+ ]
64
+
65
+ const passed = checks.filter((item) => item.status === 'passed').length
66
+ const failed = checks.length - passed
67
+ const report = {
68
+ root,
69
+ generatedAt: new Date().toISOString(),
70
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
71
+ workflows: { domainQualityGates: failed === 0 ? 'verified' : 'failed' },
72
+ limits: [
73
+ 'Domain quality gate audit verifies reusable guidance and routing; it does not run project-specific security scans, benchmarks, accessibility tools, browser tests, or API smokes.',
74
+ 'Projects must still execute the selected gates with their own commands, tools, owners, and evidence.',
75
+ ],
76
+ checks,
77
+ }
78
+
79
+ function renderMarkdown(data) {
80
+ const lines = []
81
+ lines.push('# GSE Domain Quality Gate Audit')
82
+ lines.push('')
83
+ lines.push('Generated: ' + data.generatedAt)
84
+ lines.push('Root: ' + data.root)
85
+ lines.push('')
86
+ lines.push('## Summary')
87
+ lines.push('')
88
+ lines.push('- Status: ' + data.summary.status)
89
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
90
+ lines.push('- Domain quality gates: ' + data.workflows.domainQualityGates)
91
+ lines.push('')
92
+ lines.push('## Checks')
93
+ lines.push('')
94
+ for (const item of data.checks) {
95
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
96
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
97
+ }
98
+ lines.push('')
99
+ lines.push('## Limits')
100
+ lines.push('')
101
+ for (const item of data.limits) lines.push('- ' + item)
102
+ return lines.join('\n') + '\n'
103
+ }
104
+
105
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
106
+ else console.log(renderMarkdown(report))
107
+
108
+ if (failed > 0) process.exit(1)
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs'
3
+ import os from 'node:os'
4
+ import path from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const args = process.argv.slice(2)
8
+
9
+ function readArg(name, fallback = null) {
10
+ const index = args.indexOf(name)
11
+ if (index === -1) return fallback
12
+ return args[index + 1] ?? fallback
13
+ }
14
+
15
+ const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
16
+ const targetArg = readArg('--target')
17
+ const jsonOnly = args.includes('--json')
18
+
19
+ export const evidenceLevels = [
20
+ 'result',
21
+ 'verified-unit',
22
+ 'verified-component',
23
+ 'verified-api',
24
+ 'verified-browser',
25
+ 'verified-ci',
26
+ 'accepted-owner',
27
+ 'accepted-release',
28
+ 'external-required',
29
+ ]
30
+
31
+ const levelRank = new Map([
32
+ ['result', 0],
33
+ ['verified-unit', 1],
34
+ ['verified-component', 2],
35
+ ['verified-api', 2],
36
+ ['verified-browser', 3],
37
+ ['verified-ci', 3],
38
+ ['accepted-owner', 4],
39
+ ['accepted-release', 4],
40
+ ['external-required', 0],
41
+ ])
42
+
43
+ function readText(filePath) {
44
+ return fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '') : ''
45
+ }
46
+
47
+ function readJsonl(filePath) {
48
+ if (!fs.existsSync(filePath)) return { exists: false, ok: false, records: [], error: 'missing' }
49
+ const lines = readText(filePath)
50
+ .split(/\r?\n/)
51
+ .map((line) => line.trim())
52
+ .filter(Boolean)
53
+ const records = []
54
+ for (const [index, line] of lines.entries()) {
55
+ try {
56
+ records.push(JSON.parse(line))
57
+ } catch (error) {
58
+ return { exists: true, ok: false, records, error: `line ${index + 1}: ${error.message}` }
59
+ }
60
+ }
61
+ return { exists: true, ok: true, records, error: '' }
62
+ }
63
+
64
+ export function analyzeEvidenceLevels(records) {
65
+ const allowed = new Set(evidenceLevels)
66
+ const recordsWithLevel = records.filter((record) => typeof record.evidenceLevel === 'string' && record.evidenceLevel)
67
+ const missingLevel = records.filter((record) => !record.evidenceLevel).map((record) => record.summary || record.recordType || '(unknown)')
68
+ const invalidLevel = records
69
+ .filter((record) => record.evidenceLevel && !allowed.has(record.evidenceLevel))
70
+ .map((record) => ({ summary: record.summary || record.recordType || '(unknown)', evidenceLevel: record.evidenceLevel }))
71
+ const downgraded = records
72
+ .filter((record) => record.evidenceLevel && record.requiredEvidenceLevel && allowed.has(record.evidenceLevel) && allowed.has(record.requiredEvidenceLevel))
73
+ .filter((record) => (levelRank.get(record.evidenceLevel) ?? 0) < (levelRank.get(record.requiredEvidenceLevel) ?? 0))
74
+ .map((record) => ({
75
+ summary: record.summary || record.recordType || '(unknown)',
76
+ evidenceLevel: record.evidenceLevel,
77
+ requiredEvidenceLevel: record.requiredEvidenceLevel,
78
+ }))
79
+ return {
80
+ allowed: evidenceLevels,
81
+ records: records.length,
82
+ recordsWithLevel: recordsWithLevel.length,
83
+ missingLevel,
84
+ invalidLevel,
85
+ downgraded,
86
+ }
87
+ }
88
+
89
+ function check(id, label, ok, evidence, risk = '') {
90
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
91
+ }
92
+
93
+ function createFixture() {
94
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-evidence-levels-'))
95
+ fs.mkdirSync(path.join(dir, '.gse', 'evidence'), { recursive: true })
96
+ const records = [
97
+ {
98
+ date: '2026-07-08',
99
+ recordType: 'slice',
100
+ status: 'verified',
101
+ evidenceLevel: 'verified-component',
102
+ requiredEvidenceLevel: 'verified-browser',
103
+ summary: 'UI component proof is downgraded from required browser proof.',
104
+ evidenceFile: '.gse/evidence/2026-07-08.md',
105
+ commands: ['pnpm test component'],
106
+ nextAction: 'Run browser smoke before release.',
107
+ },
108
+ {
109
+ date: '2026-07-08',
110
+ recordType: 'slice',
111
+ status: 'verified',
112
+ evidenceLevel: 'verified-browser',
113
+ requiredEvidenceLevel: 'verified-browser',
114
+ summary: 'Browser proof satisfies UI requirement.',
115
+ evidenceFile: '.gse/evidence/2026-07-08.md',
116
+ commands: ['pnpm smoke browser'],
117
+ nextAction: 'Close slice.',
118
+ },
119
+ {
120
+ date: '2026-07-08',
121
+ recordType: 'release',
122
+ status: 'result',
123
+ evidenceLevel: 'external-required',
124
+ requiredEvidenceLevel: 'accepted-release',
125
+ summary: 'Release evidence still needs owner or external acceptance.',
126
+ evidenceFile: '.gse/evidence/2026-07-08.md',
127
+ commands: ['gse owner-actions'],
128
+ nextAction: 'Collect external gate.',
129
+ },
130
+ ]
131
+ fs.writeFileSync(path.join(dir, '.gse', 'evidence', 'index.jsonl'), records.map((record) => JSON.stringify(record)).join('\n') + '\n', 'utf8')
132
+ fs.writeFileSync(path.join(dir, '.gse', 'evidence', '2026-07-08.md'), '# Evidence\n', 'utf8')
133
+ return dir
134
+ }
135
+
136
+ function audit(target) {
137
+ const resolvedTarget = path.resolve(target)
138
+ const taxonomy = readText(path.join(root, 'references', 'evidence-taxonomy.md'))
139
+ const qualityGates = readText(path.join(root, 'references', 'quality-gates.md'))
140
+ const closeGate = readText(path.join(root, 'scripts', 'audit-close-gate.mjs'))
141
+ const continuePacket = readText(path.join(root, 'scripts', 'generate-continue-packet.mjs'))
142
+ const validationProfile = readText(path.join(root, 'scripts', 'run-validation-profile.mjs'))
143
+ const validator = readText(path.join(root, 'scripts', 'validate-gse.mjs'))
144
+ const evidenceIndex = readJsonl(path.join(resolvedTarget, '.gse', 'evidence', 'index.jsonl'))
145
+ const analysis = analyzeEvidenceLevels(evidenceIndex.records)
146
+ const fixtureRecords = [
147
+ {
148
+ status: 'verified',
149
+ evidenceLevel: 'verified-component',
150
+ requiredEvidenceLevel: 'verified-browser',
151
+ summary: 'fixture component downgrade',
152
+ },
153
+ {
154
+ status: 'verified',
155
+ evidenceLevel: 'verified-browser',
156
+ requiredEvidenceLevel: 'verified-browser',
157
+ summary: 'fixture browser proof',
158
+ },
159
+ ]
160
+ const fixtureAnalysis = analyzeEvidenceLevels(fixtureRecords)
161
+
162
+ const requiredTerms = [
163
+ 'Evidence Level',
164
+ 'verified-unit',
165
+ 'verified-component',
166
+ 'verified-api',
167
+ 'verified-browser',
168
+ 'verified-ci',
169
+ 'accepted-owner',
170
+ 'accepted-release',
171
+ 'external-required',
172
+ 'Evidence status answers whether the work is result, verified, or accepted.',
173
+ 'Evidence level answers what kind of proof produced that status.',
174
+ ]
175
+
176
+ const checks = [
177
+ check('EL01', 'taxonomy defines all evidence levels and separates status from level', requiredTerms.every((term) => taxonomy.includes(term)), 'references/evidence-taxonomy.md'),
178
+ check('EL02', 'quality gates require explicit evidence level for UI/browser/API/CI claims', qualityGates.includes('Evidence level uses `evidence-taxonomy.md`') && qualityGates.includes('verified-browser') && qualityGates.includes('verified-component'), 'references/quality-gates.md'),
179
+ check('EL03', 'continue packet exposes latest evidence level and downgrade summary', continuePacket.includes('analyzeEvidenceLevels') && continuePacket.includes('evidenceLevels') && continuePacket.includes('latestEvidenceLevel'), 'scripts/generate-continue-packet.mjs'),
180
+ check('EL04', 'close gate checks evidence level validity and downgrade warnings', closeGate.includes('analyzeEvidenceLevels') && closeGate.includes('CG09') && closeGate.includes('evidence level'), 'scripts/audit-close-gate.mjs'),
181
+ check('EL05', 'validation routes include evidence level audit', validationProfile.includes('audit-evidence-levels.mjs') && validator.includes('audit-evidence-levels.mjs'), 'validation profile and validate-gse'),
182
+ check('EL06', 'target evidence index parses', evidenceIndex.ok, evidenceIndex.ok ? `${evidenceIndex.records.length} record(s)` : evidenceIndex.error),
183
+ check('EL07', 'target evidence levels are valid when present', analysis.invalidLevel.length === 0, analysis.invalidLevel.length ? JSON.stringify(analysis.invalidLevel) : 'no invalid evidence levels'),
184
+ check('EL08', 'fixture detects downgraded UI/browser proof without failing parse', fixtureAnalysis.downgraded.length === 1 && fixtureAnalysis.invalidLevel.length === 0, `${fixtureAnalysis.downgraded.length} downgrade(s), ${fixtureAnalysis.invalidLevel.length} invalid level(s)`),
185
+ ]
186
+ const passed = checks.filter((item) => item.status === 'passed').length
187
+ const failed = checks.length - passed
188
+ return {
189
+ target: resolvedTarget,
190
+ generatedAt: new Date().toISOString(),
191
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
192
+ workflows: {
193
+ evidenceLevels: failed === 0 ? 'verified' : 'failed',
194
+ recordsWithLevel: analysis.recordsWithLevel,
195
+ missingLevel: analysis.missingLevel.length,
196
+ downgraded: analysis.downgraded.length,
197
+ },
198
+ evidenceLevels: analysis,
199
+ checks,
200
+ limits: [
201
+ 'Evidence level is a proof-strength dimension; it does not replace result/verified/accepted status.',
202
+ 'Missing evidenceLevel is tolerated for historical records but should be added to new records.',
203
+ 'Downgraded evidence is surfaced as a warning path in continue/close gates; project policy decides whether it blocks close.',
204
+ ],
205
+ }
206
+ }
207
+
208
+ const isCli = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])
209
+
210
+ if (isCli) {
211
+ const target = targetArg || createFixture()
212
+ const report = audit(target)
213
+
214
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
215
+ else console.log(JSON.stringify(report, null, 2))
216
+ if (report.summary.status === 'failed') process.exit(1)
217
+ }