@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,132 +1,132 @@
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 { spawnSync } from 'node:child_process'
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 recordPath = readArg('--record')
17
- const jsonOnly = args.includes('--json')
18
-
19
- function read(relativePathOrFullPath) {
20
- const fullPath = path.isAbsolute(relativePathOrFullPath) ? relativePathOrFullPath : path.join(root, relativePathOrFullPath)
21
- return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8').replace(/^\uFEFF/, '') : ''
22
- }
23
-
24
- function exists(relativePath) {
25
- return fs.existsSync(path.join(root, relativePath))
26
- }
27
-
28
- function run(script, commandArgs) {
29
- const result = spawnSync(process.execPath, [path.join(root, 'scripts', script), ...commandArgs], {
30
- cwd: root,
31
- encoding: 'utf8',
32
- windowsHide: true,
33
- })
34
- return {
35
- command: [process.execPath, path.join(root, 'scripts', script), ...commandArgs].join(' '),
36
- status: result.status ?? 1,
37
- stdout: (result.stdout ?? '').trim(),
38
- stderr: (result.stderr ?? '').trim(),
39
- }
40
- }
41
-
42
- function parseJson(text) {
43
- try { return JSON.parse(text) } catch { return null }
44
- }
45
-
46
- function check(id, label, ok, evidence, risk = '') {
47
- return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
48
- }
49
-
50
- const target = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-host-ui-'))
51
- fs.mkdirSync(target, { recursive: true })
52
- fs.writeFileSync(path.join(target, 'AGENTS.md'), '# Host UI Fixture\n', 'utf8')
53
- const initRun = run('init-project.mjs', ['--target', target, '--mode', 'enterprise', '--json'])
54
- const adapterRun = run('generate-command-adapter.mjs', ['--target', target, '--host', 'all', '--json'])
55
- const commandRun = run('run-gse-command.mjs', ['--target', target, '--command', '/gse help', '--json'])
56
- const adapterData = parseJson(adapterRun.stdout)
57
- const commandData = parseJson(commandRun.stdout)
58
- const claudeCommand = read(path.join(target, '.claude', 'commands', 'gse.md'))
59
- const codexPointer = read(path.join(target, '.codex', 'gse-command.md'))
60
- const record = recordPath ? read(path.resolve(recordPath)) : ''
61
- const recordHasEvidence =
62
- Boolean(record) &&
63
- record.includes('## Host') &&
64
- record.includes('## Command') &&
65
- record.includes('## Result') &&
66
- record.includes('## Evidence') &&
67
- /Status:\s*(verified|accepted)/i.test(record)
68
-
69
- const checks = [
70
- check('HUI01', 'host UI invocation record template exists', exists('assets/templates/host-ui-invocation-record.md'), 'assets/templates/host-ui-invocation-record.md'),
71
- check('HUI02', 'portable runner can execute command semantics', commandRun.status === 0 && commandData?.route?.route === 'references/commands.md', '/gse help through run-gse-command.mjs'),
72
- check('HUI03', 'Claude command adapter is generated at current native path', adapterRun.status === 0 && fs.existsSync(path.join(target, '.claude', 'commands', 'gse.md')) && claudeCommand.includes('Portable execution path'), '.claude/commands/gse.md'),
73
- check('HUI04', 'Codex command pointer is generated without native claim', adapterRun.status === 0 && fs.existsSync(path.join(target, '.codex', 'gse-command.md')) && codexPointer.includes('not proof of a native project-level /gse slash-command mechanism'), '.codex/gse-command.md'),
74
- check('HUI05', 'adapter generator labels native support honestly', adapterData?.results?.some((item) => item.host === 'claude' && item.nativeSlashCommand === true) && adapterData?.results?.some((item) => item.host === 'codex' && item.nativeSlashCommand === false), 'generate-command-adapter.mjs result metadata'),
75
- check('HUI06', 'commands reference requires host runtime evidence', read('references/commands.md').includes('host-specific smoke') && read('references/commands.md').includes('Do not claim native slash-command support unless the current host exposes it and it was verified.'), 'references/commands.md'),
76
- check('HUI07', 'optional real host invocation record is valid when supplied', recordPath ? recordHasEvidence : true, recordPath ? recordPath : 'no --record supplied; template/readiness only'),
77
- check('HUI08', 'validator includes host UI invocation audit', read('scripts/validate-gse.mjs').includes('audit-host-ui-invocation.mjs'), 'scripts/validate-gse.mjs'),
78
- ]
79
-
80
- fs.rmSync(target, { recursive: true, force: true })
81
-
82
- const passed = checks.filter((item) => item.status === 'passed').length
83
- const failed = checks.length - passed
84
- const report = {
85
- root,
86
- generatedAt: new Date().toISOString(),
87
- summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
88
- workflows: {
89
- hostUiInvocationReadiness: failed === 0 ? 'verified' : 'failed',
90
- realHostUiInvocation: recordHasEvidence ? 'verified-by-record' : 'not-verified',
91
- },
92
- acceptedBy: recordHasEvidence ? 'host invocation record' : 'not accepted; no real host UI invocation record was supplied',
93
- limits: [
94
- 'This audit verifies portable command execution, generated host pointers, and the evidence format for real host UI invocation.',
95
- 'Without --record, it does not prove a real Codex, Claude Code, Hermes, WorkBuddy, or other UI invoked the command.',
96
- 'Generated adapters are not runtime proof by themselves.',
97
- ],
98
- checks,
99
- }
100
-
101
- function renderMarkdown(data) {
102
- const lines = []
103
- lines.push('# GSE Host UI Invocation Audit')
104
- lines.push('')
105
- lines.push('Generated: ' + data.generatedAt)
106
- lines.push('Root: ' + data.root)
107
- lines.push('')
108
- lines.push('## Summary')
109
- lines.push('')
110
- lines.push('- Status: ' + data.summary.status)
111
- lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
112
- lines.push('- Host UI invocation readiness: ' + data.workflows.hostUiInvocationReadiness)
113
- lines.push('- Real host UI invocation: ' + data.workflows.realHostUiInvocation)
114
- lines.push('- Accepted by: ' + data.acceptedBy)
115
- lines.push('')
116
- lines.push('## Checks')
117
- lines.push('')
118
- for (const item of data.checks) {
119
- const marker = item.status === 'passed' ? '[x]' : '[ ]'
120
- lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
121
- }
122
- lines.push('')
123
- lines.push('## Limits')
124
- lines.push('')
125
- for (const item of data.limits) lines.push('- ' + item)
126
- return lines.join('\n') + '\n'
127
- }
128
-
129
- if (jsonOnly) console.log(JSON.stringify(report, null, 2))
130
- else console.log(renderMarkdown(report))
131
-
132
- if (failed > 0) process.exit(1)
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 { spawnSync } from 'node:child_process'
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 recordPath = readArg('--record')
17
+ const jsonOnly = args.includes('--json')
18
+
19
+ function read(relativePathOrFullPath) {
20
+ const fullPath = path.isAbsolute(relativePathOrFullPath) ? relativePathOrFullPath : path.join(root, relativePathOrFullPath)
21
+ return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8').replace(/^\uFEFF/, '') : ''
22
+ }
23
+
24
+ function exists(relativePath) {
25
+ return fs.existsSync(path.join(root, relativePath))
26
+ }
27
+
28
+ function run(script, commandArgs) {
29
+ const result = spawnSync(process.execPath, [path.join(root, 'scripts', script), ...commandArgs], {
30
+ cwd: root,
31
+ encoding: 'utf8',
32
+ windowsHide: true,
33
+ })
34
+ return {
35
+ command: [process.execPath, path.join(root, 'scripts', script), ...commandArgs].join(' '),
36
+ status: result.status ?? 1,
37
+ stdout: (result.stdout ?? '').trim(),
38
+ stderr: (result.stderr ?? '').trim(),
39
+ }
40
+ }
41
+
42
+ function parseJson(text) {
43
+ try { return JSON.parse(text) } catch { return null }
44
+ }
45
+
46
+ function check(id, label, ok, evidence, risk = '') {
47
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
48
+ }
49
+
50
+ const target = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-host-ui-'))
51
+ fs.mkdirSync(target, { recursive: true })
52
+ fs.writeFileSync(path.join(target, 'AGENTS.md'), '# Host UI Fixture\n', 'utf8')
53
+ const initRun = run('init-project.mjs', ['--target', target, '--mode', 'enterprise', '--json'])
54
+ const adapterRun = run('generate-command-adapter.mjs', ['--target', target, '--host', 'all', '--json'])
55
+ const commandRun = run('run-gse-command.mjs', ['--target', target, '--command', '/gse help', '--json'])
56
+ const adapterData = parseJson(adapterRun.stdout)
57
+ const commandData = parseJson(commandRun.stdout)
58
+ const claudeCommand = read(path.join(target, '.claude', 'commands', 'gse.md'))
59
+ const codexPointer = read(path.join(target, '.codex', 'gse-command.md'))
60
+ const record = recordPath ? read(path.resolve(recordPath)) : ''
61
+ const recordHasEvidence =
62
+ Boolean(record) &&
63
+ record.includes('## Host') &&
64
+ record.includes('## Command') &&
65
+ record.includes('## Result') &&
66
+ record.includes('## Evidence') &&
67
+ /Status:\s*(verified|accepted)/i.test(record)
68
+
69
+ const checks = [
70
+ check('HUI01', 'host UI invocation record template exists', exists('assets/templates/host-ui-invocation-record.md'), 'assets/templates/host-ui-invocation-record.md'),
71
+ check('HUI02', 'portable runner can execute command semantics', commandRun.status === 0 && commandData?.route?.route === 'references/commands.md', '/gse help through run-gse-command.mjs'),
72
+ check('HUI03', 'Claude command adapter is generated at current native path', adapterRun.status === 0 && fs.existsSync(path.join(target, '.claude', 'commands', 'gse.md')) && claudeCommand.includes('Portable execution path'), '.claude/commands/gse.md'),
73
+ check('HUI04', 'Codex command pointer is generated without native claim', adapterRun.status === 0 && fs.existsSync(path.join(target, '.codex', 'gse-command.md')) && codexPointer.includes('not proof of a native project-level /gse slash-command mechanism'), '.codex/gse-command.md'),
74
+ check('HUI05', 'adapter generator labels native support honestly', adapterData?.results?.some((item) => item.host === 'claude' && item.nativeSlashCommand === true) && adapterData?.results?.some((item) => item.host === 'codex' && item.nativeSlashCommand === false), 'generate-command-adapter.mjs result metadata'),
75
+ check('HUI06', 'commands reference requires host runtime evidence', read('references/commands.md').includes('host-specific smoke') && read('references/commands.md').includes('Do not claim native slash-command support unless the current host exposes it and it was verified.'), 'references/commands.md'),
76
+ check('HUI07', 'optional real host invocation record is valid when supplied', recordPath ? recordHasEvidence : true, recordPath ? recordPath : 'no --record supplied; template/readiness only'),
77
+ check('HUI08', 'validator includes host UI invocation audit', read('scripts/validate-gse.mjs').includes('audit-host-ui-invocation.mjs'), 'scripts/validate-gse.mjs'),
78
+ ]
79
+
80
+ fs.rmSync(target, { recursive: true, force: true })
81
+
82
+ const passed = checks.filter((item) => item.status === 'passed').length
83
+ const failed = checks.length - passed
84
+ const report = {
85
+ root,
86
+ generatedAt: new Date().toISOString(),
87
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
88
+ workflows: {
89
+ hostUiInvocationReadiness: failed === 0 ? 'verified' : 'failed',
90
+ realHostUiInvocation: recordHasEvidence ? 'verified-by-record' : 'not-verified',
91
+ },
92
+ acceptedBy: recordHasEvidence ? 'host invocation record' : 'not accepted; no real host UI invocation record was supplied',
93
+ limits: [
94
+ 'This audit verifies portable command execution, generated host pointers, and the evidence format for real host UI invocation.',
95
+ 'Without --record, it does not prove a real Codex, Claude Code, Hermes, WorkBuddy, or other UI invoked the command.',
96
+ 'Generated adapters are not runtime proof by themselves.',
97
+ ],
98
+ checks,
99
+ }
100
+
101
+ function renderMarkdown(data) {
102
+ const lines = []
103
+ lines.push('# GSE Host UI Invocation Audit')
104
+ lines.push('')
105
+ lines.push('Generated: ' + data.generatedAt)
106
+ lines.push('Root: ' + data.root)
107
+ lines.push('')
108
+ lines.push('## Summary')
109
+ lines.push('')
110
+ lines.push('- Status: ' + data.summary.status)
111
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
112
+ lines.push('- Host UI invocation readiness: ' + data.workflows.hostUiInvocationReadiness)
113
+ lines.push('- Real host UI invocation: ' + data.workflows.realHostUiInvocation)
114
+ lines.push('- Accepted by: ' + data.acceptedBy)
115
+ lines.push('')
116
+ lines.push('## Checks')
117
+ lines.push('')
118
+ for (const item of data.checks) {
119
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
120
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
121
+ }
122
+ lines.push('')
123
+ lines.push('## Limits')
124
+ lines.push('')
125
+ for (const item of data.limits) lines.push('- ' + item)
126
+ return lines.join('\n') + '\n'
127
+ }
128
+
129
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
130
+ else console.log(renderMarkdown(report))
131
+
132
+ if (failed > 0) process.exit(1)
@@ -0,0 +1,203 @@
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 crypto from 'node:crypto'
6
+ import { spawnSync } from 'node:child_process'
7
+
8
+ const args = process.argv.slice(2)
9
+
10
+ function readArg(name, fallback = null) {
11
+ const index = args.indexOf(name)
12
+ if (index === -1) return fallback
13
+ return args[index + 1] ?? fallback
14
+ }
15
+
16
+ const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
17
+ const installedRootArg = readArg('--installed-root', process.env.GSE_INSTALLED_SKILL_ROOT || null)
18
+ const installedRoot = installedRootArg ? path.resolve(installedRootArg) : null
19
+ const jsonOnly = args.includes('--json')
20
+
21
+ function run(command, commandArgs, cwd = root) {
22
+ const result = spawnSync(command, commandArgs, {
23
+ cwd,
24
+ encoding: 'utf8',
25
+ windowsHide: true,
26
+ })
27
+ return {
28
+ command: [command, ...commandArgs].join(' '),
29
+ status: result.status ?? 1,
30
+ stdout: (result.stdout ?? '').trim(),
31
+ stderr: (result.stderr ?? '').trim(),
32
+ }
33
+ }
34
+
35
+ function parseJson(text) {
36
+ try {
37
+ return JSON.parse(text)
38
+ } catch {
39
+ return null
40
+ }
41
+ }
42
+
43
+ function exists(relativePath, base = root) {
44
+ return fs.existsSync(path.join(base, relativePath))
45
+ }
46
+
47
+ function sha256(filePath) {
48
+ return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex')
49
+ }
50
+
51
+ function check(id, label, ok, evidence, risk = '') {
52
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
53
+ }
54
+
55
+ function packageToTemp() {
56
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-installed-sync-'))
57
+ const packageOut = path.join(tempRoot, 'package')
58
+ const packageRun = run(process.execPath, [
59
+ path.join(root, 'scripts', 'package-gse.mjs'),
60
+ '--root',
61
+ root,
62
+ '--out',
63
+ packageOut,
64
+ '--label',
65
+ 'installed-sync',
66
+ '--force',
67
+ '--json',
68
+ ])
69
+ const manifestPath = path.join(packageOut, 'gse-package-manifest.json')
70
+ const manifest = fs.existsSync(manifestPath) ? parseJson(fs.readFileSync(manifestPath, 'utf8')) : null
71
+ return { tempRoot, packageOut, packageRun, manifest }
72
+ }
73
+
74
+ function compareInstalled(manifest, targetRoot) {
75
+ if (!targetRoot) return { compared: 0, missing: [], mismatched: [] }
76
+ const missing = []
77
+ const mismatched = []
78
+ const fileHashes = manifest?.fileHashes ?? {}
79
+ for (const [relativePath, expectedHash] of Object.entries(fileHashes)) {
80
+ const targetPath = path.join(targetRoot, relativePath)
81
+ if (!fs.existsSync(targetPath)) {
82
+ missing.push(relativePath)
83
+ continue
84
+ }
85
+ const actualHash = sha256(targetPath)
86
+ if (actualHash !== expectedHash) mismatched.push(relativePath)
87
+ }
88
+ return {
89
+ compared: Object.keys(fileHashes).length,
90
+ missing,
91
+ mismatched,
92
+ }
93
+ }
94
+
95
+ const { tempRoot, packageOut, packageRun, manifest } = packageToTemp()
96
+ const packageJson = exists('package.json') ? parseJson(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) : null
97
+ const packageCopyJson = exists('package.json', packageOut) ? parseJson(fs.readFileSync(path.join(packageOut, 'package.json'), 'utf8')) : null
98
+ const installedComparison = compareInstalled(manifest, installedRoot)
99
+ const installedCommand = installedRoot
100
+ ? run(process.execPath, [
101
+ path.join(installedRoot, 'scripts', 'run-gse-command.mjs'),
102
+ '--root',
103
+ installedRoot,
104
+ '--target',
105
+ installedRoot,
106
+ '--command',
107
+ '/gse maintenance --package-smoke --skip-release-bundle',
108
+ '--json',
109
+ '--compact',
110
+ ], installedRoot)
111
+ : null
112
+ const installedCommandData = installedCommand ? parseJson(installedCommand.stdout) : null
113
+
114
+ const requiredPackageFiles = [
115
+ 'SKILL.md',
116
+ 'package.json',
117
+ 'references/commands.md',
118
+ 'references/maintenance-cadence.md',
119
+ 'scripts/backfill-evidence-levels.mjs',
120
+ 'scripts/audit-evidence-review-queue.mjs',
121
+ 'scripts/audit-installed-sync.mjs',
122
+ 'scripts/audit-session-sync.mjs',
123
+ 'scripts/audit-maintenance-snapshot.mjs',
124
+ 'scripts/generate-maintenance-snapshot.mjs',
125
+ 'scripts/audit-maintenance-cadence.mjs',
126
+ 'scripts/record-session-sync.mjs',
127
+ 'scripts/run-gse-command.mjs',
128
+ 'scripts/validate-gse.mjs',
129
+ ]
130
+
131
+ const checks = [
132
+ check('IS01', 'package-gse creates a fresh package manifest', packageRun.status === 0 && manifest?.fileCount > 20 && Boolean(manifest?.integrity?.packageDigest), packageRun.command),
133
+ check('IS02', 'package manifest includes installed sync entrypoint and maintenance command support', manifest?.files?.includes('scripts/audit-installed-sync.mjs') && manifest?.files?.includes('scripts/audit-maintenance-cadence.mjs') && manifest?.files?.includes('references/maintenance-cadence.md'), 'gse-package-manifest.json'),
134
+ check('IS03', 'required package files are present in the package output', requiredPackageFiles.every((file) => exists(file, packageOut)), requiredPackageFiles.join(', ')),
135
+ check('IS04', 'package copy preserves package metadata version', packageJson?.version && packageCopyJson?.version === packageJson.version, `source=${packageJson?.version ?? 'missing'}, package=${packageCopyJson?.version ?? 'missing'}`),
136
+ check('IS05', 'package manifest does not expose the source root', manifest && !JSON.stringify(manifest).includes(root), 'gse-package-manifest.json'),
137
+ installedRoot
138
+ ? check('IS06', 'installed root exists and contains GSE entrypoint', exists('SKILL.md', installedRoot) && exists('scripts/run-gse-command.mjs', installedRoot), installedRoot)
139
+ : check('IS06', 'installed root comparison is optional and explicit', true, 'no --installed-root supplied; package self-check only'),
140
+ installedRoot
141
+ ? check('IS07', 'installed root matches fresh package file hashes', installedComparison.compared > 20 && installedComparison.missing.length === 0 && installedComparison.mismatched.length === 0, `compared=${installedComparison.compared}, missing=${installedComparison.missing.length}, mismatched=${installedComparison.mismatched.length}`, 'Run the install/sync step again before claiming the installed skill is fresh.')
142
+ : check('IS07', 'installed hash comparison skipped without installed root', true, 'supply --installed-root to compare a real installed copy'),
143
+ installedRoot
144
+ ? check('IS08', 'installed copy can run package-only /gse maintenance smoke', installedCommand?.status === 0 && installedCommandData?.summary?.failed === 0, installedCommand?.command ?? 'not run')
145
+ : check('IS08', 'installed command smoke skipped without installed root', true, 'supply --installed-root to run installed command smoke'),
146
+ ]
147
+
148
+ const passed = checks.filter((item) => item.status === 'passed').length
149
+ const failed = checks.length - passed
150
+ const report = {
151
+ root,
152
+ installedRoot,
153
+ generatedAt: new Date().toISOString(),
154
+ tempRoot,
155
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
156
+ workflows: {
157
+ freshPackage: packageRun.status === 0 ? 'verified' : 'failed',
158
+ installedSync: installedRoot ? failed === 0 ? 'verified' : 'failed' : 'not-requested',
159
+ installedCommandSmoke: installedRoot ? installedCommand?.status === 0 ? 'verified' : 'failed' : 'not-requested',
160
+ },
161
+ comparison: installedComparison,
162
+ limits: [
163
+ 'Without --installed-root this audit verifies fresh package contents only.',
164
+ 'With --installed-root it compares every packaged file hash against the installed copy and runs a package-only /gse maintenance smoke from that installed copy.',
165
+ 'This audit does not publish a package, update npm, or prove native host slash-command support.',
166
+ ],
167
+ checks,
168
+ }
169
+
170
+ function renderMarkdown(data) {
171
+ const lines = []
172
+ lines.push('# GSE Installed Sync Audit')
173
+ lines.push('')
174
+ lines.push('Generated: ' + data.generatedAt)
175
+ lines.push('Root: ' + data.root)
176
+ lines.push('Installed root: ' + (data.installedRoot ?? 'not provided'))
177
+ lines.push('')
178
+ lines.push('## Summary')
179
+ lines.push('')
180
+ lines.push('- Status: ' + data.summary.status)
181
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
182
+ lines.push('- Fresh package: ' + data.workflows.freshPackage)
183
+ lines.push('- Installed sync: ' + data.workflows.installedSync)
184
+ lines.push('')
185
+ lines.push('## Checks')
186
+ lines.push('')
187
+ for (const item of data.checks) {
188
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
189
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
190
+ }
191
+ lines.push('')
192
+ lines.push('## Limits')
193
+ lines.push('')
194
+ for (const item of data.limits) lines.push('- ' + item)
195
+ return lines.join('\n') + '\n'
196
+ }
197
+
198
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
199
+ else console.log(renderMarkdown(report))
200
+
201
+ fs.rmSync(tempRoot, { recursive: true, force: true })
202
+
203
+ if (failed > 0) process.exit(1)