@t275005746/gse 0.1.0

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 (207) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +42 -0
  2. package/.github/ISSUE_TEMPLATE/change_request.yml +50 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +38 -0
  5. package/.github/workflows/validate-gse.yml +33 -0
  6. package/.gse/README.md +18 -0
  7. package/.gse/gse-development-protocol.md +50 -0
  8. package/.gse/project-profile.md +29 -0
  9. package/.gse/quality-gates.md +25 -0
  10. package/.gse/releases/public-channel-publication-pending.md +49 -0
  11. package/.gse/releases/public-ci-run-pending.md +53 -0
  12. package/.gse/releases/public-release-owner-required.md +65 -0
  13. package/.gse/releases/public-repository-settings-owner-required.md +59 -0
  14. package/.gse/releases/public-security-contact-owner-required.md +45 -0
  15. package/.gse/state.json +27 -0
  16. package/CHANGELOG.md +24 -0
  17. package/CONTRIBUTING.md +64 -0
  18. package/LICENSE +21 -0
  19. package/README.md +236 -0
  20. package/README.zh-CN.md +236 -0
  21. package/SECURITY.md +41 -0
  22. package/SKILL.md +148 -0
  23. package/SUPPORT.md +38 -0
  24. package/agents/openai.yaml +4 -0
  25. package/assets/marketplace/README.md +7 -0
  26. package/assets/marketplace/gse-listing.json +75 -0
  27. package/assets/templates/acceptance-execution-packet.md +73 -0
  28. package/assets/templates/adr.md +14 -0
  29. package/assets/templates/change-brief.md +16 -0
  30. package/assets/templates/design.md +18 -0
  31. package/assets/templates/dispatch-packet.md +104 -0
  32. package/assets/templates/evidence.md +14 -0
  33. package/assets/templates/execution-quality-pack.md +65 -0
  34. package/assets/templates/goal-map.md +21 -0
  35. package/assets/templates/host-adapter.md +48 -0
  36. package/assets/templates/host-ui-invocation-record.md +42 -0
  37. package/assets/templates/incident-review.md +60 -0
  38. package/assets/templates/public-channel-publication-record.md +49 -0
  39. package/assets/templates/public-ci-run-record.md +53 -0
  40. package/assets/templates/public-release-record.md +65 -0
  41. package/assets/templates/public-repository-settings-record.md +59 -0
  42. package/assets/templates/public-security-contact-record.md +45 -0
  43. package/assets/templates/release-trust-record.md +32 -0
  44. package/assets/templates/review.md +18 -0
  45. package/assets/templates/spec.md +16 -0
  46. package/assets/templates/target-adoption-evidence.md +29 -0
  47. package/assets/templates/tasks.md +17 -0
  48. package/assets/templates/update-release-acceptance-record.md +58 -0
  49. package/examples/README.md +22 -0
  50. package/examples/agent-runtime-host/.claude/gse-adapter.md +6 -0
  51. package/examples/agent-runtime-host/.codex/gse-adapter.md +7 -0
  52. package/examples/agent-runtime-host/.gse/goal-map.md +7 -0
  53. package/examples/agent-runtime-host/.gse/project-profile.md +27 -0
  54. package/examples/agent-runtime-host/.gse/tooling.md +5 -0
  55. package/examples/agent-runtime-host/.mcp.json +9 -0
  56. package/examples/agent-runtime-host/AGENTS.md +5 -0
  57. package/examples/agent-runtime-host/README.md +10 -0
  58. package/examples/agent-runtime-host/docs/model-routing.md +5 -0
  59. package/examples/cli-tool/.gse/project-profile.md +21 -0
  60. package/examples/cli-tool/AGENTS.md +5 -0
  61. package/examples/cli-tool/README.md +12 -0
  62. package/examples/cli-tool/package.json +21 -0
  63. package/examples/small-app/.env.example +2 -0
  64. package/examples/small-app/.github/workflows/ci.yml +8 -0
  65. package/examples/small-app/AGENTS.md +5 -0
  66. package/examples/small-app/README.md +12 -0
  67. package/examples/small-app/package.json +26 -0
  68. package/examples/small-app/playwright.config.ts +4 -0
  69. package/package.json +53 -0
  70. package/references/adoption-recipes.md +171 -0
  71. package/references/agent-roles.md +49 -0
  72. package/references/architecture-health.md +101 -0
  73. package/references/benchmark-audit.md +73 -0
  74. package/references/commands.md +295 -0
  75. package/references/community-channels.md +46 -0
  76. package/references/compatibility.md +70 -0
  77. package/references/design-basis.md +38 -0
  78. package/references/domain-model.md +129 -0
  79. package/references/domain-quality-gates.md +75 -0
  80. package/references/drift-audit.md +81 -0
  81. package/references/evidence-taxonomy.md +123 -0
  82. package/references/file-ownership.md +107 -0
  83. package/references/final-readiness.md +84 -0
  84. package/references/forward-test.md +133 -0
  85. package/references/goal-map.md +36 -0
  86. package/references/host-adapters.md +119 -0
  87. package/references/learning-system.md +35 -0
  88. package/references/marketplace-discovery.md +46 -0
  89. package/references/model-routing.md +103 -0
  90. package/references/open-source-defaults.md +39 -0
  91. package/references/operating-model.md +52 -0
  92. package/references/packaging.md +277 -0
  93. package/references/project-agent-workspace.md +89 -0
  94. package/references/project-bootstrap.md +122 -0
  95. package/references/project-profile.md +57 -0
  96. package/references/public-release.md +174 -0
  97. package/references/quality-gates.md +100 -0
  98. package/references/recovery.md +176 -0
  99. package/references/release-trust.md +43 -0
  100. package/references/release.md +126 -0
  101. package/references/review.md +141 -0
  102. package/references/router.md +90 -0
  103. package/references/spec-workflow.md +66 -0
  104. package/references/task-levels.md +81 -0
  105. package/references/tool-adapters.md +73 -0
  106. package/scripts/audit-acceptance-execution-packet.mjs +133 -0
  107. package/scripts/audit-adoption-recipes.mjs +99 -0
  108. package/scripts/audit-adoption.mjs +154 -0
  109. package/scripts/audit-change-lifecycle.mjs +77 -0
  110. package/scripts/audit-change-system.mjs +134 -0
  111. package/scripts/audit-ci-readiness.mjs +107 -0
  112. package/scripts/audit-close-gate.mjs +323 -0
  113. package/scripts/audit-command-adapters.mjs +91 -0
  114. package/scripts/audit-command-execution.mjs +210 -0
  115. package/scripts/audit-commands.mjs +117 -0
  116. package/scripts/audit-compatibility.mjs +149 -0
  117. package/scripts/audit-completion-readiness.mjs +292 -0
  118. package/scripts/audit-distribution.mjs +251 -0
  119. package/scripts/audit-domain-quality-gates.mjs +108 -0
  120. package/scripts/audit-evidence-placeholders.mjs +126 -0
  121. package/scripts/audit-final-acceptance-packet.mjs +148 -0
  122. package/scripts/audit-final-form-progress-report.mjs +161 -0
  123. package/scripts/audit-final-form-stale-copy.mjs +221 -0
  124. package/scripts/audit-final-readiness-promotion.mjs +255 -0
  125. package/scripts/audit-final-readiness.mjs +226 -0
  126. package/scripts/audit-fixtures.mjs +154 -0
  127. package/scripts/audit-fresh-session-readiness.mjs +177 -0
  128. package/scripts/audit-gse.mjs +275 -0
  129. package/scripts/audit-host-adapters.mjs +119 -0
  130. package/scripts/audit-host-runtime-evidence-handoff.mjs +159 -0
  131. package/scripts/audit-host-runtime-invocation-drill.mjs +240 -0
  132. package/scripts/audit-host-runtime-invocations.mjs +254 -0
  133. package/scripts/audit-host-ui-invocation.mjs +132 -0
  134. package/scripts/audit-learning-system.mjs +103 -0
  135. package/scripts/audit-local-final-form-completion.mjs +131 -0
  136. package/scripts/audit-marketplace-discovery.mjs +122 -0
  137. package/scripts/audit-npm-package-metadata.mjs +155 -0
  138. package/scripts/audit-npm-publish-dry-run.mjs +169 -0
  139. package/scripts/audit-npm-tarball-install.mjs +191 -0
  140. package/scripts/audit-open-source-defaults.mjs +92 -0
  141. package/scripts/audit-open-source-readiness.mjs +97 -0
  142. package/scripts/audit-owner-external-gate-kit.mjs +218 -0
  143. package/scripts/audit-project.mjs +323 -0
  144. package/scripts/audit-public-acceptance-command-dry-run-drill.mjs +203 -0
  145. package/scripts/audit-public-acceptance-handoff.mjs +142 -0
  146. package/scripts/audit-public-acceptance-readiness.mjs +224 -0
  147. package/scripts/audit-public-channel-publication.mjs +248 -0
  148. package/scripts/audit-public-ci-run.mjs +184 -0
  149. package/scripts/audit-public-collaboration-templates.mjs +98 -0
  150. package/scripts/audit-public-external-gate-probe.mjs +206 -0
  151. package/scripts/audit-public-release-checklist.mjs +133 -0
  152. package/scripts/audit-public-release-decision.mjs +201 -0
  153. package/scripts/audit-public-release-metadata.mjs +176 -0
  154. package/scripts/audit-public-repository-settings.mjs +237 -0
  155. package/scripts/audit-public-security-contact.mjs +171 -0
  156. package/scripts/audit-readme-docs.mjs +185 -0
  157. package/scripts/audit-recovery-readiness.mjs +98 -0
  158. package/scripts/audit-release-bundle.mjs +251 -0
  159. package/scripts/audit-release-owner-action-plan-drill.mjs +277 -0
  160. package/scripts/audit-release-owner-action-plan.mjs +164 -0
  161. package/scripts/audit-release-readiness.mjs +106 -0
  162. package/scripts/audit-release-status-manifest.mjs +165 -0
  163. package/scripts/audit-release-trust.mjs +62 -0
  164. package/scripts/audit-remote-distribution.mjs +266 -0
  165. package/scripts/audit-roadmap-consistency.mjs +235 -0
  166. package/scripts/audit-signing.mjs +147 -0
  167. package/scripts/audit-state-freshness.mjs +113 -0
  168. package/scripts/audit-target-adoption-evidence.mjs +117 -0
  169. package/scripts/audit-target-project.mjs +507 -0
  170. package/scripts/audit-update-release-acceptance.mjs +136 -0
  171. package/scripts/audit-v1-target-validation.mjs +269 -0
  172. package/scripts/audit-validation-profiles.mjs +125 -0
  173. package/scripts/close-change.mjs +116 -0
  174. package/scripts/discover-project-profile.mjs +307 -0
  175. package/scripts/forward-test-gse.mjs +146 -0
  176. package/scripts/generate-command-adapter.mjs +231 -0
  177. package/scripts/generate-final-acceptance-packet.mjs +181 -0
  178. package/scripts/generate-final-form-progress-report.mjs +205 -0
  179. package/scripts/generate-host-adapter.mjs +73 -0
  180. package/scripts/generate-host-runtime-evidence-handoff.mjs +206 -0
  181. package/scripts/generate-owner-external-gate-kit.mjs +295 -0
  182. package/scripts/generate-public-acceptance-handoff.mjs +168 -0
  183. package/scripts/generate-public-release-checklist.mjs +207 -0
  184. package/scripts/generate-release-bundle.mjs +505 -0
  185. package/scripts/generate-release-owner-action-plan.mjs +172 -0
  186. package/scripts/generate-release-status-manifest.mjs +200 -0
  187. package/scripts/generate-session-prompt.mjs +188 -0
  188. package/scripts/gse.mjs +67 -0
  189. package/scripts/init-change.mjs +265 -0
  190. package/scripts/init-project.mjs +785 -0
  191. package/scripts/install-gse.mjs +234 -0
  192. package/scripts/lib/evidence-placeholders.mjs +28 -0
  193. package/scripts/package-gse.mjs +174 -0
  194. package/scripts/probe-public-external-gates.mjs +167 -0
  195. package/scripts/record-host-invocation.mjs +151 -0
  196. package/scripts/record-learning.mjs +137 -0
  197. package/scripts/record-public-channel-publication.mjs +178 -0
  198. package/scripts/record-public-ci-run.mjs +180 -0
  199. package/scripts/record-public-release.mjs +175 -0
  200. package/scripts/record-public-repository-settings.mjs +209 -0
  201. package/scripts/record-public-security-contact.mjs +157 -0
  202. package/scripts/run-gse-command.mjs +538 -0
  203. package/scripts/run-validation-profile.mjs +146 -0
  204. package/scripts/sign-gse-package.mjs +83 -0
  205. package/scripts/update-project-state.mjs +223 -0
  206. package/scripts/validate-gse.mjs +1168 -0
  207. package/scripts/verify-gse-package.mjs +85 -0
@@ -0,0 +1,538 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+ import { spawnSync } from 'node:child_process'
5
+
6
+ const args = process.argv.slice(2)
7
+
8
+ function readArg(name, fallback = null) {
9
+ const index = args.indexOf(name)
10
+ if (index === -1) return fallback
11
+ return args[index + 1] ?? fallback
12
+ }
13
+
14
+ const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
15
+ const target = path.resolve(readArg('--target', process.cwd()))
16
+ const commandText = readArg('--command', args.find((item) => item.startsWith('/gse') || item.startsWith('gse ')) ?? '/gse help')
17
+ const jsonOnly = args.includes('--json')
18
+ const execute = args.includes('--execute')
19
+ const compactOutput = args.includes('--compact')
20
+
21
+ function readJson(relativePath) {
22
+ const fullPath = path.join(target, relativePath)
23
+ if (!fs.existsSync(fullPath)) return null
24
+ try {
25
+ return JSON.parse(fs.readFileSync(fullPath, 'utf8').replace(/^\uFEFF/, ''))
26
+ } catch {
27
+ return null
28
+ }
29
+ }
30
+
31
+ function exists(relativePath) {
32
+ return fs.existsSync(path.join(target, relativePath))
33
+ }
34
+
35
+ function runNode(script, commandArgs) {
36
+ const result = spawnSync(process.execPath, [path.join(root, 'scripts', script), ...commandArgs], {
37
+ cwd: root,
38
+ encoding: 'utf8',
39
+ windowsHide: true,
40
+ })
41
+ const stdout = (result.stdout ?? '').trim()
42
+ let diagnosticSummary = null
43
+ try {
44
+ const parsed = JSON.parse(stdout)
45
+ if (parsed?.summary && typeof parsed.summary.failed === 'number') {
46
+ diagnosticSummary = parsed.summary
47
+ }
48
+ } catch {
49
+ diagnosticSummary = null
50
+ }
51
+ const status = result.status ?? 1
52
+ const ok = status === 0 || (diagnosticSummary && diagnosticSummary.failed === 0)
53
+ return {
54
+ command: [process.execPath, path.join(root, 'scripts', script), ...commandArgs].join(' '),
55
+ status,
56
+ ok,
57
+ diagnosticSummary,
58
+ stdout,
59
+ stderr: (result.stderr ?? '').trim(),
60
+ }
61
+ }
62
+
63
+ function normalizeCommand(value) {
64
+ return String(value || '')
65
+ .trim()
66
+ .replace(/^gse\b/i, '/gse')
67
+ .replace(/\s+/g, ' ')
68
+ }
69
+
70
+ function readRestValue(items, name, fallback = '') {
71
+ const index = items.indexOf(name)
72
+ if (index === -1) return fallback
73
+ const values = []
74
+ for (let cursor = index + 1; cursor < items.length; cursor += 1) {
75
+ const item = items[cursor]
76
+ if (item.startsWith('--')) break
77
+ values.push(item)
78
+ }
79
+ return values.join(' ').replace(/^["']|["']$/g, '').trim() || fallback
80
+ }
81
+
82
+ const normalized = normalizeCommand(commandText)
83
+ const parts = normalized.split(' ')
84
+ const verb = parts[0] === '/gse' ? (parts[1] || 'help') : 'help'
85
+ const rest = parts.slice(2)
86
+ const state = readJson('.gse/state.json')
87
+ const projectProfile = exists('.gse/project-profile.md')
88
+ const goalMap = exists('.gse/goal-map.md')
89
+ const qualityGates = exists('.gse/quality-gates.md')
90
+ const canonicalPlan = state?.canonicalPlan ?? null
91
+
92
+ const commandMap = {
93
+ help: {
94
+ route: 'references/commands.md',
95
+ effect: 'read-only',
96
+ summary: 'Show GSE commands and project entry files.',
97
+ },
98
+ continue: {
99
+ route: 'scripts/generate-session-prompt.mjs',
100
+ effect: 'read-only',
101
+ summary: 'Generate a continuation packet from project state.',
102
+ },
103
+ next: {
104
+ route: 'scripts/generate-session-prompt.mjs',
105
+ effect: 'read-only',
106
+ summary: 'Alias for /gse continue.',
107
+ },
108
+ status: {
109
+ route: 'scripts/generate-final-form-progress-report.mjs or .gse/state.json',
110
+ effect: 'read-only',
111
+ summary: 'Show project state, or GSE final-form progress when the target is the GSE skill.',
112
+ },
113
+ doctor: {
114
+ route: 'scripts/audit-public-acceptance-readiness.mjs or scripts/audit-target-project.mjs',
115
+ effect: 'read-only',
116
+ summary: 'Diagnose final-form public/host acceptance blockers for GSE, or target-project GSE readiness for normal projects.',
117
+ },
118
+ acceptance: {
119
+ route: 'scripts/audit-public-acceptance-readiness.mjs or scripts/audit-target-project.mjs',
120
+ effect: 'read-only',
121
+ summary: 'Alias for /gse doctor focused on final acceptance boundaries.',
122
+ },
123
+ 'owner-actions': {
124
+ route: 'scripts/audit-public-acceptance-readiness.mjs',
125
+ effect: 'read-only',
126
+ summary: 'Show the remaining owner/external actions required before public acceptance.',
127
+ },
128
+ probe: {
129
+ route: 'scripts/probe-public-external-gates.mjs',
130
+ effect: 'read-only',
131
+ summary: 'Probe supplied owner/external evidence locations before accepted records are written.',
132
+ },
133
+ release: {
134
+ route: 'scripts/generate-release-bundle.mjs or scripts/audit-release-bundle.mjs',
135
+ effect: 'read-only by default; write-with-execute for canonical bundle generation',
136
+ summary: 'Dry-run or generate a release bundle for open-source/package handoff.',
137
+ },
138
+ package: {
139
+ route: 'scripts/package-gse.mjs',
140
+ effect: 'read-only by default; write-with-execute for local package generation',
141
+ summary: 'Dry-run or generate a local installable GSE package.',
142
+ },
143
+ install: {
144
+ route: 'scripts/install-gse.mjs',
145
+ effect: 'read-only by default; write-with-execute for install target writes',
146
+ summary: 'Dry-run or install GSE from a local package path or URL-shaped package source.',
147
+ },
148
+ 'public-release': {
149
+ route: 'scripts/generate-public-release-checklist.mjs or scripts/audit-public-release-checklist.mjs',
150
+ effect: 'read-only by default; write-with-execute for canonical checklist generation',
151
+ summary: 'Dry-run or generate the ordered owner/public release checklist.',
152
+ },
153
+ owner: {
154
+ route: 'scripts/audit-public-acceptance-readiness.mjs',
155
+ effect: 'read-only',
156
+ summary: 'Alias for /gse owner-actions.',
157
+ },
158
+ audit: {
159
+ route: 'scripts/audit-target-project.mjs',
160
+ effect: 'read-only',
161
+ summary: 'Audit target project GSE readiness.',
162
+ },
163
+ close: {
164
+ route: 'scripts/audit-close-gate.mjs',
165
+ effect: 'read-only',
166
+ summary: 'Check whether current slice can close.',
167
+ },
168
+ verify: {
169
+ route: 'references/quality-gates.md',
170
+ effect: 'read-only',
171
+ summary: 'Select and run focused verification according to project quality gates.',
172
+ },
173
+ learn: {
174
+ route: 'scripts/record-learning.mjs',
175
+ effect: 'read-only by default; write-with-execute for .gse/learnings.md',
176
+ summary: 'Record a reusable project lesson and skip duplicate summaries.',
177
+ },
178
+ slice: {
179
+ route: 'references/spec-workflow.md',
180
+ effect: 'read-only',
181
+ summary: 'Normalize outcome, scope, acceptance, evidence, risk, and next action.',
182
+ },
183
+ init: {
184
+ route: 'scripts/init-project.mjs',
185
+ effect: 'write-with-execute',
186
+ summary: 'Initialize .gse scaffold when --execute is supplied.',
187
+ },
188
+ adopt: {
189
+ route: 'references/adoption-recipes.md',
190
+ effect: 'write-with-execute',
191
+ summary: 'Adopt GSE without overwriting local rules.',
192
+ },
193
+ change: {
194
+ route: 'scripts/init-change.mjs',
195
+ effect: 'write-with-execute',
196
+ summary: 'Create a change pack when --execute is supplied.',
197
+ },
198
+ }
199
+
200
+ const route = commandMap[verb] ?? commandMap.help
201
+ let execution = null
202
+
203
+ if (execute && verb === 'init') {
204
+ const mode = rest.includes('--mode') ? rest[rest.indexOf('--mode') + 1] : 'auto'
205
+ execution = runNode('init-project.mjs', ['--target', target, '--mode', mode, '--json'])
206
+ } else if (execute && verb === 'change') {
207
+ const changeId = rest.find((item) => !item.startsWith('--')) ?? 'gse-change'
208
+ const level = rest.includes('--level') ? rest[rest.indexOf('--level') + 1] : 'standard'
209
+ execution = runNode('init-change.mjs', ['--target', target, '--change-id', changeId, '--level', level, '--json'])
210
+ } else if (verb === 'continue' || verb === 'next') {
211
+ execution = runNode('generate-session-prompt.mjs', ['--target', target, '--json'])
212
+ } else if (verb === 'status') {
213
+ const targetHasFinalFormReport = fs.existsSync(path.join(target, 'scripts', 'generate-final-form-progress-report.mjs'))
214
+ && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
215
+ execution = targetHasFinalFormReport
216
+ ? runNode('generate-final-form-progress-report.mjs', ['--root', target, '--dry-run', '--json'])
217
+ : {
218
+ command: 'read .gse/state.json',
219
+ status: state ? 0 : 1,
220
+ ok: Boolean(state),
221
+ diagnosticSummary: state ? { status: 'passed', failed: 0, total: 1 } : { status: 'failed', failed: 1, total: 1 },
222
+ stdout: JSON.stringify({
223
+ status: state ? 'ready' : 'missing-state',
224
+ target,
225
+ state: state ?? null,
226
+ project: {
227
+ hasGse: exists('.gse'),
228
+ projectProfile,
229
+ goalMap,
230
+ qualityGates,
231
+ canonicalPlan,
232
+ canonicalPlanExists: canonicalPlan ? exists(canonicalPlan) : null,
233
+ },
234
+ limits: [
235
+ 'Generic project status reports .gse/state.json only.',
236
+ 'Final-form progress report is available when the target is the GSE skill package.',
237
+ ],
238
+ }),
239
+ stderr: state ? '' : '.gse/state.json is missing or invalid',
240
+ }
241
+ } else if (verb === 'doctor' || verb === 'acceptance') {
242
+ const targetHasPublicAcceptanceDoctor = fs.existsSync(path.join(target, 'scripts', 'audit-public-acceptance-readiness.mjs'))
243
+ && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
244
+ execution = targetHasPublicAcceptanceDoctor
245
+ ? runNode('audit-public-acceptance-readiness.mjs', ['--root', target, '--json'])
246
+ : runNode('audit-target-project.mjs', ['--target', target, '--json'])
247
+ } else if (verb === 'owner-actions' || verb === 'owner') {
248
+ const targetHasPublicAcceptanceDoctor = fs.existsSync(path.join(target, 'scripts', 'audit-public-acceptance-readiness.mjs'))
249
+ && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
250
+ if (targetHasPublicAcceptanceDoctor) {
251
+ const doctor = runNode('audit-public-acceptance-readiness.mjs', ['--root', target, '--json'])
252
+ let compact = null
253
+ try {
254
+ const parsed = JSON.parse(doctor.stdout)
255
+ compact = {
256
+ status: parsed.summary?.status ?? 'unknown',
257
+ publicAccepted: parsed.summary?.publicAccepted ?? 'unknown',
258
+ pendingGateCount: parsed.summary?.pendingGates ?? 0,
259
+ actions: (parsed.pendingGates ?? []).map((gate, index) => ({
260
+ order: String(index + 1).padStart(2, '0'),
261
+ area: gate.area,
262
+ owner: gate.owner,
263
+ status: gate.status,
264
+ requiredEvidence: gate.requiredEvidence,
265
+ recordCommand: gate.recordCommand,
266
+ preflightCommand: gate.preflightCommand,
267
+ })),
268
+ verificationCommands: [
269
+ 'node scripts/run-gse-command.mjs --root __GSE__ --target __GSE__ --command "/gse probe --public-repo-url __PUBLIC_REPO_URL__ --security-contact-url __SECURITY_CONTACT_URL__ --public-ci-run-url __PUBLIC_CI_RUN_URL__ --registry-package-url __REGISTRY_PACKAGE_URL__ --marketplace-url __MARKETPLACE_LISTING_URL__ --native-host-evidence __NATIVE_HOST_EVIDENCE__ --other-host-evidence __OTHER_HOST_EVIDENCE__" --json',
270
+ 'node scripts/audit-public-acceptance-readiness.mjs --root __GSE__ --json',
271
+ 'node scripts/audit-final-readiness.mjs --root __GSE__ --json',
272
+ 'node scripts/audit-owner-external-gate-kit.mjs --root __GSE__ --json',
273
+ ],
274
+ limits: [
275
+ 'These are owner/external collection actions, not public acceptance.',
276
+ 'Run preflight commands first, then record real accepted evidence when available.',
277
+ ],
278
+ }
279
+ } catch {
280
+ compact = null
281
+ }
282
+ execution = {
283
+ ...doctor,
284
+ command: doctor.command + ' -> compact owner actions',
285
+ stdout: compact ? JSON.stringify(compact, null, 2) : doctor.stdout,
286
+ }
287
+ } else {
288
+ execution = {
289
+ command: 'read target final-readiness/public-acceptance support',
290
+ status: 1,
291
+ ok: false,
292
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
293
+ stdout: JSON.stringify({
294
+ status: 'unsupported-target',
295
+ target,
296
+ error: '/gse owner-actions is only available for GSE skill packages with public acceptance audits.',
297
+ }),
298
+ stderr: 'target does not expose scripts/audit-public-acceptance-readiness.mjs and references/final-readiness.md',
299
+ }
300
+ }
301
+ } else if (verb === 'probe') {
302
+ const targetHasProbe = fs.existsSync(path.join(target, 'scripts', 'probe-public-external-gates.mjs'))
303
+ if (targetHasProbe) {
304
+ const passthrough = []
305
+ const allowedValueFlags = new Set([
306
+ '--public-repo-url',
307
+ '--security-contact-url',
308
+ '--public-ci-run-url',
309
+ '--registry-package-url',
310
+ '--marketplace-url',
311
+ '--native-host-evidence',
312
+ '--other-host-evidence',
313
+ '--timeout-ms',
314
+ ])
315
+ const allowedBooleanFlags = new Set(['--allow-local-fixture'])
316
+ for (let index = 0; index < rest.length; index += 1) {
317
+ const item = rest[index]
318
+ if (allowedBooleanFlags.has(item)) {
319
+ passthrough.push(item)
320
+ } else if (allowedValueFlags.has(item)) {
321
+ passthrough.push(item, rest[index + 1] ?? '')
322
+ index += 1
323
+ }
324
+ }
325
+ execution = runNode('probe-public-external-gates.mjs', ['--root', target, ...passthrough, '--json'])
326
+ } else {
327
+ execution = {
328
+ command: 'read target public external gate probe support',
329
+ status: 1,
330
+ ok: false,
331
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
332
+ stdout: JSON.stringify({
333
+ status: 'unsupported-target',
334
+ target,
335
+ error: '/gse probe is only available for GSE skill packages that include scripts/probe-public-external-gates.mjs.',
336
+ }),
337
+ stderr: 'target does not expose scripts/probe-public-external-gates.mjs',
338
+ }
339
+ }
340
+ } else if (verb === 'release') {
341
+ const targetHasReleaseBundle = fs.existsSync(path.join(target, 'scripts', 'generate-release-bundle.mjs'))
342
+ && fs.existsSync(path.join(target, 'scripts', 'audit-release-bundle.mjs'))
343
+ if (targetHasReleaseBundle) {
344
+ const labelIndex = rest.indexOf('--label')
345
+ const outIndex = rest.indexOf('--out')
346
+ const label = labelIndex === -1 ? 'gse-release-bundle-audit' : (rest[labelIndex + 1] || 'gse-release-bundle-audit')
347
+ const out = outIndex === -1 ? path.join(target, '.gse', 'release-bundles', label) : path.resolve(rest[outIndex + 1] || path.join(target, '.gse', 'release-bundles', label))
348
+ execution = execute
349
+ ? runNode('generate-release-bundle.mjs', ['--root', target, '--label', label, '--out', out, '--force', '--json'])
350
+ : runNode('generate-release-bundle.mjs', ['--root', target, '--label', label, '--out', out, '--dry-run', '--json'])
351
+ } else {
352
+ execution = {
353
+ command: 'read target release bundle support',
354
+ status: 1,
355
+ ok: false,
356
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
357
+ stdout: JSON.stringify({
358
+ status: 'unsupported-target',
359
+ target,
360
+ error: '/gse release is only available for GSE skill packages that include release bundle scripts.',
361
+ }),
362
+ stderr: 'target does not expose scripts/generate-release-bundle.mjs and scripts/audit-release-bundle.mjs',
363
+ }
364
+ }
365
+ } else if (verb === 'package') {
366
+ const targetHasPackageScript = fs.existsSync(path.join(target, 'scripts', 'package-gse.mjs'))
367
+ if (targetHasPackageScript) {
368
+ const labelIndex = rest.indexOf('--label')
369
+ const outIndex = rest.indexOf('--out')
370
+ const label = labelIndex === -1 ? 'gse-command-package' : (rest[labelIndex + 1] || 'gse-command-package')
371
+ const out = outIndex === -1 ? path.join(target, '.gse', 'packages', label) : path.resolve(rest[outIndex + 1] || path.join(target, '.gse', 'packages', label))
372
+ execution = execute
373
+ ? runNode('package-gse.mjs', ['--root', target, '--label', label, '--out', out, '--force', '--json'])
374
+ : runNode('package-gse.mjs', ['--root', target, '--label', label, '--out', out, '--dry-run', '--json'])
375
+ } else {
376
+ execution = {
377
+ command: 'read target package support',
378
+ status: 1,
379
+ ok: false,
380
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
381
+ stdout: JSON.stringify({
382
+ status: 'unsupported-target',
383
+ target,
384
+ error: '/gse package is only available for GSE skill packages that include scripts/package-gse.mjs.',
385
+ }),
386
+ stderr: 'target does not expose scripts/package-gse.mjs',
387
+ }
388
+ }
389
+ } else if (verb === 'install') {
390
+ const targetHasInstallScript = fs.existsSync(path.join(target, 'scripts', 'install-gse.mjs'))
391
+ if (targetHasInstallScript) {
392
+ const sourceIndex = rest.indexOf('--source')
393
+ const sourceUrlIndex = rest.indexOf('--source-url')
394
+ const manifestUrlIndex = rest.indexOf('--manifest-url')
395
+ const installTargetIndex = rest.indexOf('--install-target')
396
+ const legacyTargetIndex = rest.indexOf('--target')
397
+ const publicKeyIndex = rest.indexOf('--public-key')
398
+ const packageSource = sourceIndex === -1 ? null : path.resolve(rest[sourceIndex + 1] || '')
399
+ const packageSourceUrl = sourceUrlIndex === -1 ? null : (rest[sourceUrlIndex + 1] || '')
400
+ const manifestUrl = manifestUrlIndex === -1 ? null : (rest[manifestUrlIndex + 1] || '')
401
+ const installTarget = installTargetIndex !== -1
402
+ ? path.resolve(rest[installTargetIndex + 1] || '')
403
+ : legacyTargetIndex !== -1
404
+ ? path.resolve(rest[legacyTargetIndex + 1] || '')
405
+ : null
406
+ const publicKey = publicKeyIndex === -1 ? null : path.resolve(rest[publicKeyIndex + 1] || '')
407
+ if (!installTarget || (!packageSource && !packageSourceUrl && !manifestUrl)) {
408
+ execution = {
409
+ command: 'parse /gse install arguments',
410
+ status: 0,
411
+ ok: true,
412
+ diagnosticSummary: { status: 'waiting-for-input', failed: 0, total: 1 },
413
+ stdout: JSON.stringify({
414
+ status: 'waiting-for-input',
415
+ target,
416
+ required: ['--source <package-dir> or --source-url <package-url>', '--install-target <install-skill-dir>'],
417
+ example: '/gse install --source __PACKAGE_DIR__ --install-target __INSTALL_SKILL_DIR__',
418
+ effect: 'read-only by default; add --execute to write the install target',
419
+ }),
420
+ stderr: '',
421
+ }
422
+ } else {
423
+ const installArgs = ['--target', installTarget, '--json']
424
+ if (packageSource) installArgs.push('--source', packageSource)
425
+ if (packageSourceUrl) installArgs.push('--source-url', packageSourceUrl)
426
+ if (manifestUrl) installArgs.push('--manifest-url', manifestUrl)
427
+ if (publicKey) installArgs.push('--public-key', publicKey)
428
+ if (rest.includes('--skip-integrity')) installArgs.push('--skip-integrity')
429
+ if (rest.includes('--skip-signature')) installArgs.push('--skip-signature')
430
+ execution = execute
431
+ ? runNode('install-gse.mjs', [...installArgs, '--force'])
432
+ : runNode('install-gse.mjs', [...installArgs, '--dry-run'])
433
+ }
434
+ } else {
435
+ execution = {
436
+ command: 'read target install support',
437
+ status: 1,
438
+ ok: false,
439
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
440
+ stdout: JSON.stringify({
441
+ status: 'unsupported-target',
442
+ target,
443
+ error: '/gse install is only available for GSE skill packages that include scripts/install-gse.mjs.',
444
+ }),
445
+ stderr: 'target does not expose scripts/install-gse.mjs',
446
+ }
447
+ }
448
+ } else if (verb === 'public-release') {
449
+ const targetHasPublicReleaseChecklist = fs.existsSync(path.join(target, 'scripts', 'generate-public-release-checklist.mjs'))
450
+ && fs.existsSync(path.join(target, 'scripts', 'audit-public-release-checklist.mjs'))
451
+ if (targetHasPublicReleaseChecklist) {
452
+ const outIndex = rest.indexOf('--out')
453
+ const manifestIndex = rest.indexOf('--manifest')
454
+ const out = outIndex === -1
455
+ ? path.join(target, '.gse', 'acceptance', 'public-release-checklist.md')
456
+ : path.resolve(rest[outIndex + 1] || path.join(target, '.gse', 'acceptance', 'public-release-checklist.md'))
457
+ const checklistArgs = ['--root', target, '--out', out, '--json']
458
+ if (manifestIndex !== -1) checklistArgs.push('--manifest', path.resolve(rest[manifestIndex + 1] || path.join(target, '.gse', 'acceptance', 'release-status-manifest.json')))
459
+ execution = execute
460
+ ? runNode('generate-public-release-checklist.mjs', [...checklistArgs, '--force'])
461
+ : runNode('generate-public-release-checklist.mjs', [...checklistArgs, '--dry-run'])
462
+ } else {
463
+ execution = {
464
+ command: 'read target public release checklist support',
465
+ status: 1,
466
+ ok: false,
467
+ diagnosticSummary: { status: 'failed', failed: 1, total: 1 },
468
+ stdout: JSON.stringify({
469
+ status: 'unsupported-target',
470
+ target,
471
+ error: '/gse public-release is only available for GSE skill packages that include public release checklist scripts.',
472
+ }),
473
+ stderr: 'target does not expose scripts/generate-public-release-checklist.mjs and scripts/audit-public-release-checklist.mjs',
474
+ }
475
+ }
476
+ } else if (verb === 'audit') {
477
+ execution = runNode('audit-target-project.mjs', ['--target', target, '--json'])
478
+ } else if (verb === 'close') {
479
+ execution = runNode('audit-close-gate.mjs', ['--target', target, '--json'])
480
+ } else if (verb === 'verify') {
481
+ const profileIndex = rest.indexOf('--profile')
482
+ const profile = profileIndex === -1 ? 'lite' : (rest[profileIndex + 1] || 'lite')
483
+ execution = runNode('run-validation-profile.mjs', ['--target', target, '--profile', profile, '--json'])
484
+ } else if (verb === 'learn') {
485
+ const learningArgs = [
486
+ '--target', target,
487
+ '--summary', readRestValue(rest, '--summary'),
488
+ '--trigger', readRestValue(rest, '--trigger', 'reusable lesson'),
489
+ '--source', readRestValue(rest, '--source', 'run-gse-command'),
490
+ '--promotion', readRestValue(rest, '--promotion', 'first occurrence: learning note'),
491
+ '--json',
492
+ ]
493
+ const impact = readRestValue(rest, '--impact')
494
+ if (impact) learningArgs.push('--impact', impact)
495
+ if (execute) learningArgs.push('--execute')
496
+ execution = runNode('record-learning.mjs', learningArgs)
497
+ }
498
+
499
+ const report = {
500
+ root,
501
+ target,
502
+ command: normalized,
503
+ verb,
504
+ route,
505
+ project: {
506
+ hasGse: exists('.gse'),
507
+ projectProfile,
508
+ goalMap,
509
+ qualityGates,
510
+ stateValid: Boolean(state),
511
+ phase: state?.phase ?? null,
512
+ currentSlice: state?.currentSlice ?? null,
513
+ canonicalPlan,
514
+ canonicalPlanExists: canonicalPlan ? exists(canonicalPlan) : null,
515
+ },
516
+ execution,
517
+ limits: [
518
+ 'This runner executes portable GSE command semantics.',
519
+ 'It does not prove a host UI accepted a native slash command unless the host invokes this runner or a host smoke records that behavior.',
520
+ 'Write-capable commands require --execute.',
521
+ ],
522
+ }
523
+
524
+ if (jsonOnly && compactOutput && execution?.stdout) {
525
+ try {
526
+ console.log(JSON.stringify(JSON.parse(execution.stdout), null, 2))
527
+ } catch {
528
+ console.log(execution.stdout)
529
+ }
530
+ } else if (jsonOnly) console.log(JSON.stringify(report, null, 2))
531
+ else {
532
+ console.log('GSE command: ' + report.command)
533
+ console.log('Route: ' + report.route.route)
534
+ console.log('Effect: ' + report.route.effect)
535
+ console.log('Target: ' + report.target)
536
+ }
537
+
538
+ if (execution && !execution.ok) process.exit(1)
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+ import { spawnSync } from 'node:child_process'
5
+
6
+ const args = process.argv.slice(2)
7
+
8
+ function readArg(name, fallback = null) {
9
+ const index = args.indexOf(name)
10
+ if (index === -1) return fallback
11
+ return args[index + 1] ?? fallback
12
+ }
13
+
14
+ const root = path.resolve(readArg('--root', path.join(import.meta.dirname, '..')))
15
+ const target = path.resolve(readArg('--target', root))
16
+ const profile = readArg('--profile', 'lite')
17
+ const jsonOnly = args.includes('--json')
18
+
19
+ function scriptExists(name) {
20
+ return fs.existsSync(path.join(root, 'scripts', name))
21
+ }
22
+
23
+ function run(script, commandArgs) {
24
+ const result = spawnSync(process.execPath, [path.join(root, 'scripts', script), ...commandArgs], {
25
+ cwd: root,
26
+ encoding: 'utf8',
27
+ windowsHide: true,
28
+ })
29
+ const stdout = (result.stdout ?? '').trim()
30
+ let parsed = null
31
+ try {
32
+ parsed = JSON.parse(stdout)
33
+ } catch {
34
+ parsed = null
35
+ }
36
+ const failed = parsed?.summary?.failed
37
+ const ok = (result.status ?? 1) === 0 || failed === 0
38
+ return {
39
+ script,
40
+ command: [process.execPath, path.join(root, 'scripts', script), ...commandArgs].join(' '),
41
+ status: result.status ?? 1,
42
+ ok,
43
+ summary: parsed?.summary ?? null,
44
+ workflows: parsed?.workflows ?? null,
45
+ stdout,
46
+ stderr: (result.stderr ?? '').trim(),
47
+ }
48
+ }
49
+
50
+ function commandList(selectedProfile) {
51
+ const common = [
52
+ ['audit-commands.mjs', ['--root', root, '--json']],
53
+ ['audit-command-execution.mjs', ['--root', root, '--profile', 'lite', '--json']],
54
+ ['audit-learning-system.mjs', ['--root', root, '--json']],
55
+ ]
56
+
57
+ const targetChecks = target === root
58
+ ? []
59
+ : [['audit-target-project.mjs', ['--root', root, '--target', target, '--json']]]
60
+ const closeChecks = [
61
+ ['audit-close-gate.mjs', ['--target', target, '--json']],
62
+ ]
63
+
64
+ const gseFinalChecks = []
65
+ if (target === root && scriptExists('audit-final-form-progress-report.mjs')) {
66
+ gseFinalChecks.push(['audit-final-form-progress-report.mjs', ['--root', root, '--json']])
67
+ }
68
+
69
+ const releaseChecks = [
70
+ ['audit-command-execution.mjs', ['--root', root, '--profile', 'full', '--json']],
71
+ ['audit-npm-package-metadata.mjs', ['--root', root, '--json']],
72
+ ['audit-npm-tarball-install.mjs', ['--root', root, '--json']],
73
+ ['audit-signing.mjs', ['--root', root, '--json']],
74
+ ['audit-release-bundle.mjs', ['--root', root, '--json']],
75
+ ['audit-distribution.mjs', ['--root', root, '--json']],
76
+ ['audit-remote-distribution.mjs', ['--root', root, '--json']],
77
+ ['audit-public-acceptance-readiness.mjs', ['--root', root, '--json']],
78
+ ['audit-final-readiness.mjs', ['--root', root, '--json']],
79
+ ['audit-final-acceptance-packet.mjs', ['--root', root, '--json']],
80
+ ['audit-owner-external-gate-kit.mjs', ['--root', root, '--json']],
81
+ ]
82
+
83
+ if (selectedProfile === 'lite') return [...common, ...gseFinalChecks]
84
+ if (selectedProfile === 'standard') return [...common, ...targetChecks, ...gseFinalChecks]
85
+ if (selectedProfile === 'enterprise') return [...common, ...targetChecks, ...gseFinalChecks, ...closeChecks, ['audit-owner-external-gate-kit.mjs', ['--root', root, '--json']]]
86
+ if (selectedProfile === 'release') return [...common, ...targetChecks, ...gseFinalChecks, ...closeChecks, ...releaseChecks]
87
+ throw new Error(`Unknown validation profile: ${selectedProfile}`)
88
+ }
89
+
90
+ const selectedCommands = commandList(profile)
91
+ const results = selectedCommands.map(([script, commandArgs]) => run(script, commandArgs))
92
+ const passed = results.filter((item) => item.ok).length
93
+ const failed = results.length - passed
94
+ const report = {
95
+ root,
96
+ target,
97
+ profile,
98
+ generatedAt: new Date().toISOString(),
99
+ summary: {
100
+ status: failed === 0 ? 'passed' : 'failed',
101
+ passed,
102
+ failed,
103
+ total: results.length,
104
+ },
105
+ workflows: {
106
+ validationProfile: failed === 0 ? 'verified' : 'failed',
107
+ profile,
108
+ },
109
+ results,
110
+ limits: [
111
+ 'Validation profiles select the lightest command set that proves the requested claim.',
112
+ 'Lite and standard profiles do not replace release, distribution, security, public acceptance, or host-native runtime evidence.',
113
+ 'Release profile may be slow and should be reserved for release/install/distribution claims.',
114
+ ],
115
+ }
116
+
117
+ function renderMarkdown(data) {
118
+ const lines = []
119
+ lines.push('# GSE Validation Profile')
120
+ lines.push('')
121
+ lines.push('Generated: ' + data.generatedAt)
122
+ lines.push('Root: ' + data.root)
123
+ lines.push('Target: ' + data.target)
124
+ lines.push('Profile: ' + data.profile)
125
+ lines.push('')
126
+ lines.push('## Summary')
127
+ lines.push('')
128
+ lines.push('- Status: ' + data.summary.status)
129
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
130
+ lines.push('')
131
+ lines.push('## Commands')
132
+ lines.push('')
133
+ for (const item of data.results) {
134
+ lines.push('- ' + (item.ok ? '[x]' : '[ ]') + ' `' + item.command + '`')
135
+ }
136
+ lines.push('')
137
+ lines.push('## Limits')
138
+ lines.push('')
139
+ for (const item of data.limits) lines.push('- ' + item)
140
+ return lines.join('\n') + '\n'
141
+ }
142
+
143
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
144
+ else console.log(renderMarkdown(report))
145
+
146
+ if (failed > 0) process.exit(1)