@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,277 @@
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 jsonOnly = args.includes('--json')
17
+
18
+ function run(command, commandArgs, cwd = root) {
19
+ const result = spawnSync(command, commandArgs, {
20
+ cwd,
21
+ encoding: 'utf8',
22
+ windowsHide: true,
23
+ })
24
+ return {
25
+ status: result.status ?? 1,
26
+ stdout: (result.stdout ?? '').trim(),
27
+ stderr: (result.stderr ?? '').trim(),
28
+ command: [command, ...commandArgs].join(' '),
29
+ }
30
+ }
31
+
32
+ function parseJson(stdout) {
33
+ try {
34
+ return JSON.parse(stdout)
35
+ } catch {
36
+ return null
37
+ }
38
+ }
39
+
40
+ function check(id, label, ok, evidence, risk = '') {
41
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
42
+ }
43
+
44
+ function copySkillFixture() {
45
+ const fixture = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-owner-action-plan-drill-'))
46
+ fs.cpSync(root, fixture, {
47
+ recursive: true,
48
+ filter(source) {
49
+ const normalized = source.replace(/\\/g, '/')
50
+ return !normalized.includes('/.git/') && !normalized.includes('/node_modules/')
51
+ },
52
+ })
53
+ fs.writeFileSync(path.join(fixture, 'LICENSE'), 'MIT License\n\nFixture only.\n', 'utf8')
54
+ return fixture
55
+ }
56
+
57
+ function runFixtureScript(fixture, scriptName, scriptArgs) {
58
+ return run(process.execPath, [path.join(fixture, 'scripts', scriptName), '--root', fixture, ...scriptArgs, '--force', '--json'], fixture)
59
+ }
60
+
61
+ function requiredCommandScriptsFor(gates) {
62
+ return [...new Set(gates.map((gate) => {
63
+ const match = String(gate.recordCommand ?? '').match(/scripts\/([\w-]+\.mjs)/)
64
+ return match ? match[1] : null
65
+ }).filter(Boolean))]
66
+ }
67
+
68
+ const fixture = copySkillFixture()
69
+ const manifestPath = path.join(fixture, '.gse', 'acceptance', 'release-status-manifest.json')
70
+ const planPath = path.join(fixture, '.gse', 'acceptance', 'release-owner-action-plan.md')
71
+
72
+ const generateManifest = runFixtureScript(fixture, 'generate-release-status-manifest.mjs', [
73
+ '--out', manifestPath,
74
+ ])
75
+ const generatePlan = runFixtureScript(fixture, 'generate-release-owner-action-plan.mjs', [
76
+ '--manifest', manifestPath,
77
+ '--out', planPath,
78
+ ])
79
+ const manifest = fs.existsSync(manifestPath) ? parseJson(fs.readFileSync(manifestPath, 'utf8')) : null
80
+ const plan = fs.existsSync(planPath) ? fs.readFileSync(planPath, 'utf8') : ''
81
+ const pendingGates = manifest?.publicAcceptance?.pendingGates ?? []
82
+ const commandScripts = requiredCommandScriptsFor(pendingGates)
83
+
84
+ const recordRuns = [
85
+ runFixtureScript(fixture, 'record-public-security-contact.mjs', [
86
+ '--contact-status', 'accepted',
87
+ '--contact-type', 'url',
88
+ '--contact-value', 'https://gse.dev/security',
89
+ '--evidence-owner', 'gse-maintainer',
90
+ '--evidence-date', '2026-07-06',
91
+ '--evidence-url', 'https://gse.dev/security-policy',
92
+ '--is-public', 'true',
93
+ '--security-policy-updated', 'true',
94
+ '--evidence-status', 'accepted',
95
+ '--accepted-by', 'gse-maintainer',
96
+ '--accepted-at', '2026-07-06',
97
+ '--out', path.join(fixture, '.gse', 'releases', 'fixture-public-security-contact.md'),
98
+ ]),
99
+ runFixtureScript(fixture, 'record-public-repository-settings.mjs', [
100
+ '--repository-url', 'https://github.com/gse-org/gse',
101
+ '--visibility', 'public',
102
+ '--settings-status', 'accepted',
103
+ '--evidence-owner', 'gse-maintainer',
104
+ '--evidence-date', '2026-07-06',
105
+ '--evidence-url', 'https://github.com/gse-org/gse/settings/branches',
106
+ '--issues-enabled', 'true',
107
+ '--pull-requests-enabled', 'true',
108
+ '--security-policy-visible', 'true',
109
+ '--branch-protection-enabled', 'true',
110
+ '--required-status-checks-enabled', 'true',
111
+ '--required-checks', 'Validate GSE',
112
+ '--require-review-before-merge', 'true',
113
+ '--require-conversation-resolution', 'true',
114
+ '--restrict-force-pushes', 'true',
115
+ '--restrict-deletions', 'true',
116
+ '--evidence-status', 'accepted',
117
+ '--accepted-by', 'gse-maintainer',
118
+ '--accepted-at', '2026-07-06',
119
+ '--out', path.join(fixture, '.gse', 'releases', 'fixture-public-repository-settings.md'),
120
+ ]),
121
+ runFixtureScript(fixture, 'record-public-ci-run.mjs', [
122
+ '--run-status', 'accepted',
123
+ '--run-conclusion', 'success',
124
+ '--repository-url', 'https://github.com/gse-org/gse',
125
+ '--workflow-name', 'Validate GSE',
126
+ '--workflow-file', '.github/workflows/validate-gse.yml',
127
+ '--run-url', 'https://github.com/gse-org/gse/actions/runs/123',
128
+ '--commit-sha', '0123456789abcdef0123456789abcdef01234567',
129
+ '--branch', 'main',
130
+ '--required-checks', 'Validate GSE',
131
+ '--evidence-owner', 'gse-maintainer',
132
+ '--evidence-date', '2026-07-06',
133
+ '--evidence-url', 'https://github.com/gse-org/gse/actions/runs/123',
134
+ '--evidence-status', 'accepted',
135
+ '--accepted-by', 'gse-maintainer',
136
+ '--accepted-at', '2026-07-06',
137
+ '--proves-public-ci-run', 'true',
138
+ '--proves-required-checks', 'true',
139
+ '--proves-release-commit', 'true',
140
+ '--out', path.join(fixture, '.gse', 'releases', 'fixture-public-ci-run.md'),
141
+ ]),
142
+ runFixtureScript(fixture, 'record-public-channel-publication.mjs', [
143
+ '--publication-status', 'accepted',
144
+ '--channel-type', 'package-registry',
145
+ '--channel-name', 'npm',
146
+ '--channel-url', 'https://registry.npmjs.org/gse',
147
+ '--version', '1.0.0',
148
+ '--artifact-digest', 'sha256:fixture',
149
+ '--review-status', 'published',
150
+ '--evidence-owner', 'gse-maintainer',
151
+ '--evidence-date', '2026-07-06',
152
+ '--evidence-url', 'https://registry.npmjs.org/gse/1.0.0',
153
+ '--evidence-status', 'accepted',
154
+ '--accepted-by', 'gse-maintainer',
155
+ '--accepted-at', '2026-07-06',
156
+ '--proves-registry-publication', 'true',
157
+ '--proves-channel-installability', 'true',
158
+ '--out', path.join(fixture, '.gse', 'releases', 'fixture-public-registry-publication.md'),
159
+ ]),
160
+ runFixtureScript(fixture, 'record-public-channel-publication.mjs', [
161
+ '--publication-status', 'accepted',
162
+ '--channel-type', 'marketplace',
163
+ '--channel-name', 'Codex Marketplace',
164
+ '--channel-url', 'https://marketplace.openai.com/gse',
165
+ '--version', '1.0.0',
166
+ '--review-status', 'approved',
167
+ '--evidence-owner', 'gse-maintainer',
168
+ '--evidence-date', '2026-07-06',
169
+ '--evidence-url', 'https://marketplace.openai.com/gse/review',
170
+ '--evidence-status', 'accepted',
171
+ '--accepted-by', 'gse-maintainer',
172
+ '--accepted-at', '2026-07-06',
173
+ '--proves-marketplace-approval', 'true',
174
+ '--proves-channel-installability', 'true',
175
+ '--out', path.join(fixture, '.gse', 'releases', 'fixture-marketplace-approval.md'),
176
+ ]),
177
+ runFixtureScript(fixture, 'record-host-invocation.mjs', [
178
+ '--host', 'Fixture Native Host',
179
+ '--invocation-method', 'native-slash-command',
180
+ '--command', '/gse help',
181
+ '--status', 'accepted',
182
+ '--evidence-owner', 'gse-maintainer',
183
+ '--evidence', 'fixture native slash-command transcript',
184
+ '--verification-command', 'node scripts/audit-final-readiness.mjs --root __GSE__ --json',
185
+ '--native-slash-command', 'true',
186
+ '--portable-text-command', 'false',
187
+ '--generated-pointer', 'false',
188
+ '--owner-acceptance-required', 'false',
189
+ '--out', path.join(fixture, '.gse', 'evidence', 'host-invocations', 'fixture-native-host.md'),
190
+ ]),
191
+ runFixtureScript(fixture, 'record-host-invocation.mjs', [
192
+ '--host', 'Fixture Other Host',
193
+ '--invocation-method', 'portable-command-runner',
194
+ '--command', '/gse continue',
195
+ '--status', 'accepted',
196
+ '--evidence-owner', 'gse-maintainer',
197
+ '--evidence', 'fixture other host runtime transcript',
198
+ '--verification-command', 'node scripts/audit-final-readiness.mjs --root __GSE__ --json',
199
+ '--native-slash-command', 'false',
200
+ '--portable-text-command', 'false',
201
+ '--generated-pointer', 'false',
202
+ '--owner-acceptance-required', 'false',
203
+ '--out', path.join(fixture, '.gse', 'evidence', 'host-invocations', 'fixture-other-host.md'),
204
+ ]),
205
+ ]
206
+
207
+ const finalReadiness = run(process.execPath, [path.join(fixture, 'scripts', 'audit-final-readiness.mjs'), '--root', fixture, '--json'], fixture)
208
+ const finalReadinessData = parseJson(finalReadiness.stdout)
209
+ const publicDoctor = run(process.execPath, [path.join(fixture, 'scripts', 'audit-public-acceptance-readiness.mjs'), '--root', fixture, '--json'], fixture)
210
+ const publicDoctorData = parseJson(publicDoctor.stdout)
211
+
212
+ const expectedScripts = commandScripts
213
+ const recordFailures = recordRuns.filter((item) => item.status !== 0)
214
+ const promotedRows = finalReadinessData?.matrix?.filter((row) => row.status === 'verified') ?? []
215
+
216
+ const checks = [
217
+ check('ROAD01', 'release status manifest and owner action plan generate in fixture', generateManifest.status === 0 && generatePlan.status === 0 && manifest?.publicAcceptance?.publicAccepted === 'not-accepted' && plan.includes('GSE Release Owner Action Plan'), 'generate manifest and action plan'),
218
+ check('ROAD02', 'owner action plan covers all pending gates from manifest', pendingGates.length > 0 && pendingGates.every((gate) => plan.includes(gate.area) && plan.includes(gate.recordCommand)) && !pendingGates.some((gate) => gate.area === 'License decision'), `${pendingGates.length} pending gate(s); License decision resolved`),
219
+ check('ROAD03', 'owner action plan commands map to real record scripts', expectedScripts.every((script) => commandScripts.includes(script)) && !plan.includes('proves-public-registry-publication'), commandScripts.join(', ')),
220
+ check('ROAD04', 'accepted fixture records can be created for every owner/external gate family', recordFailures.length === 0, recordFailures.map((item) => item.stderr || item.stdout || item.command).join('; ') || 'all fixture records written'),
221
+ check('ROAD05', 'final readiness promotes to publicAccepted verified after fixture records', finalReadiness.status === 0 && finalReadinessData?.workflows?.publicAccepted === 'verified' && promotedRows.length >= 22, finalReadinessData?.workflows?.publicAccepted ?? 'unknown'),
222
+ check('ROAD06', 'public acceptance doctor reports no pending gates after accepted fixture records', publicDoctor.status === 0 && publicDoctorData?.summary?.pendingGates === 0 && publicDoctorData?.summary?.publicAccepted === 'verified', `pending=${publicDoctorData?.summary?.pendingGates ?? 'unknown'}, publicAccepted=${publicDoctorData?.summary?.publicAccepted ?? 'unknown'}`),
223
+ ]
224
+
225
+ const passed = checks.filter((item) => item.status === 'passed').length
226
+ const failed = checks.length - passed
227
+ const report = {
228
+ root,
229
+ fixtureRoot: fixture,
230
+ generatedAt: new Date().toISOString(),
231
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
232
+ workflows: {
233
+ releaseOwnerActionPlanDrill: failed === 0 ? 'verified' : 'failed',
234
+ publicAcceptedFixture: finalReadinessData?.workflows?.publicAccepted ?? 'unknown',
235
+ pendingGatesAfterRecords: publicDoctorData?.summary?.pendingGates ?? 'unknown',
236
+ },
237
+ limits: [
238
+ 'This drill verifies the owner action plan path with fixture accepted records.',
239
+ 'It does not create real owner decisions, public CI runs, public repository settings, registry publications, marketplace approvals, or native host invocations.',
240
+ ],
241
+ checks,
242
+ }
243
+
244
+ function renderMarkdown(data) {
245
+ const lines = []
246
+ lines.push('# GSE Release Owner Action Plan Drill')
247
+ lines.push('')
248
+ lines.push('Generated: ' + data.generatedAt)
249
+ lines.push('Root: ' + data.root)
250
+ lines.push('Fixture root: ' + data.fixtureRoot)
251
+ lines.push('')
252
+ lines.push('## Summary')
253
+ lines.push('')
254
+ lines.push('- Status: ' + data.summary.status)
255
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
256
+ lines.push('- Public accepted fixture: ' + data.workflows.publicAcceptedFixture)
257
+ lines.push('- Pending gates after records: ' + data.workflows.pendingGatesAfterRecords)
258
+ lines.push('')
259
+ lines.push('## Checks')
260
+ lines.push('')
261
+ for (const item of data.checks) {
262
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
263
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
264
+ }
265
+ lines.push('')
266
+ lines.push('## Limits')
267
+ lines.push('')
268
+ for (const item of data.limits) lines.push('- ' + item)
269
+ return lines.join('\n') + '\n'
270
+ }
271
+
272
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
273
+ else console.log(renderMarkdown(report))
274
+
275
+ fs.rmSync(fixture, { recursive: true, force: true })
276
+
277
+ if (failed > 0) process.exit(1)
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+ import { mkdtempSync, rmSync } from 'node:fs'
5
+ import { tmpdir } from 'node:os'
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 jsonOnly = args.includes('--json')
18
+
19
+ function exists(relativePath) {
20
+ return fs.existsSync(path.join(root, relativePath))
21
+ }
22
+
23
+ function read(relativePath) {
24
+ const fullPath = path.join(root, relativePath)
25
+ return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8').replace(/^\uFEFF/, '') : ''
26
+ }
27
+
28
+ function run(command, commandArgs) {
29
+ const result = spawnSync(command, commandArgs, {
30
+ cwd: root,
31
+ encoding: 'utf8',
32
+ windowsHide: true,
33
+ })
34
+ return {
35
+ status: result.status ?? 1,
36
+ stdout: (result.stdout ?? '').trim(),
37
+ stderr: (result.stderr ?? '').trim(),
38
+ command: [command, ...commandArgs].join(' '),
39
+ }
40
+ }
41
+
42
+ function parseJson(text) {
43
+ try {
44
+ return JSON.parse(text)
45
+ } catch {
46
+ return null
47
+ }
48
+ }
49
+
50
+ function check(id, label, ok, evidence, risk = '') {
51
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
52
+ }
53
+
54
+ const generator = read('scripts/generate-release-owner-action-plan.mjs')
55
+ const validate = read('scripts/validate-gse.mjs')
56
+ const skill = read('SKILL.md')
57
+ const packaging = read('references/packaging.md')
58
+ const releaseGenerator = read('scripts/generate-release-bundle.mjs')
59
+ const releaseAudit = read('scripts/audit-release-bundle.mjs')
60
+ const tmp = mkdtempSync(path.join(tmpdir(), 'gse-release-owner-action-plan-'))
61
+ const tmpManifest = path.join(tmp, 'release-status-manifest.json')
62
+ const tmpPlan = path.join(tmp, 'release-owner-action-plan.md')
63
+ const generatedManifest = exists('scripts/generate-release-status-manifest.mjs')
64
+ ? run(process.execPath, [path.join(root, 'scripts', 'generate-release-status-manifest.mjs'), '--root', root, '--out', tmpManifest, '--force', '--json'])
65
+ : null
66
+ const generatedPlan = generatedManifest?.status === 0 && exists('scripts/generate-release-owner-action-plan.mjs')
67
+ ? run(process.execPath, [path.join(root, 'scripts', 'generate-release-owner-action-plan.mjs'), '--root', root, '--manifest', tmpManifest, '--out', tmpPlan, '--force', '--json'])
68
+ : null
69
+ const manifest = fs.existsSync(tmpManifest) ? parseJson(fs.readFileSync(tmpManifest, 'utf8')) : null
70
+ const plan = fs.existsSync(tmpPlan) ? fs.readFileSync(tmpPlan, 'utf8') : ''
71
+ const generatedData = generatedPlan ? parseJson(generatedPlan.stdout) : null
72
+ const canonicalPlan = read('.gse/acceptance/release-owner-action-plan.md')
73
+ rmSync(tmp, { recursive: true, force: true })
74
+
75
+ const pendingGates = manifest?.publicAcceptance?.pendingGates ?? []
76
+ const verifiedRows = manifest?.readiness?.verified?.length ?? 0
77
+ const ownerRequiredRows = manifest?.readiness?.ownerRequired?.length ?? 0
78
+ const externalRequiredRows = manifest?.readiness?.externalRequired?.length ?? 0
79
+ const publicAccepted = manifest?.publicAcceptance?.publicAccepted ?? manifest?.claimBoundary?.publicAccepted ?? 'unknown'
80
+ const requiredOwners = ['project owner', 'repository owner', 'external CI', 'external registry', 'external marketplace', 'host runtime']
81
+ const recordCommands = [...new Set(pendingGates
82
+ .map((gate) => String(gate.recordCommand ?? '').match(/node scripts\/([^ ]+)/)?.[1] ?? '')
83
+ .filter(Boolean))]
84
+ const planUsesCompleteRecordCommandTemplates = !plan.includes('--invocation-status') &&
85
+ !/record-[a-z-]+\.mjs[\s\S]*\.\.\./.test(plan) &&
86
+ !/record-[a-z-]+\.mjs[^\n`]*[<>]/.test(plan) &&
87
+ plan.includes('--status accepted')
88
+ const planVerificationCommandsAreShellSafe = !/(audit-[a-z-]+|validate-gse|generate-release-status-manifest)\.mjs[^\n`]*[<>]/.test(plan) &&
89
+ plan.includes('__GSE__')
90
+ const canonicalPlanMatchesCurrentManifest = canonicalPlan.includes('- Public accepted: ' + publicAccepted) &&
91
+ canonicalPlan.includes('- Verified rows: ' + verifiedRows) &&
92
+ canonicalPlan.includes('- Owner-required rows: ' + ownerRequiredRows) &&
93
+ canonicalPlan.includes('- External-required rows: ' + externalRequiredRows) &&
94
+ pendingGates.every((gate) => canonicalPlan.includes('#### ' + gate.area)) &&
95
+ !canonicalPlan.includes('#### License decision')
96
+
97
+ const checks = [
98
+ check('ROAP01', 'release owner action plan generator exists', exists('scripts/generate-release-owner-action-plan.mjs'), 'scripts/generate-release-owner-action-plan.mjs'),
99
+ check('ROAP02', 'generator reads release status manifest', generator.includes('release-status-manifest.json') && generator.includes('pendingGates') && generator.includes('recordCommand'), 'generator source'),
100
+ check('ROAP03', 'generator writes parseable action plan report', generatedPlan?.status === 0 && generatedData?.status === 'written' && plan.includes('GSE Release Owner Action Plan'), generatedPlan?.stderr || tmpPlan),
101
+ check('ROAP04', 'plan preserves public acceptance boundary', plan.includes('Public accepted: not-accepted') && plan.includes('Local validation does not mean public acceptance') && plan.includes('Native slash-command support requires a real host invocation record'), 'claim boundary'),
102
+ check('ROAP05', 'plan groups actions by responsible owner', requiredOwners.every((owner) => plan.includes(owner.replace(/\b\w/g, (char) => char.toUpperCase())) || pendingGates.every((gate) => gate.owner !== owner)), 'owner groups'),
103
+ check('ROAP06', 'plan includes every pending gate area', pendingGates.length > 0 && pendingGates.every((gate) => plan.includes(gate.area)) && !plan.includes('#### License decision'), 'pending gate areas; License decision resolved'),
104
+ check('ROAP07', 'plan includes concrete record commands', recordCommands.length > 0 && recordCommands.every((command) => plan.includes(command)), recordCommands.join(', ')),
105
+ check('ROAP08', 'plan includes dry-run preflight commands and post-action verification commands', plan.includes('Preflight command') && plan.includes('--dry-run --json') && plan.includes('validate-gse.mjs') && plan.includes('audit-public-acceptance-command-dry-run-drill.mjs') && plan.includes('audit-release-owner-action-plan.mjs') && plan.includes('generate-release-status-manifest.mjs'), 'dry-run preflight and verification commands'),
106
+ check('ROAP08b', 'plan uses complete record command templates', planUsesCompleteRecordCommandTemplates, 'no ellipsis, no stale host invocation flag, host records use --status accepted'),
107
+ check('ROAP09', 'skill routes users to release owner action plan', skill.includes('generate-release-owner-action-plan.mjs'), 'SKILL.md'),
108
+ check('ROAP10', 'packaging docs route release owner action plan', packaging.includes('generate-release-owner-action-plan.mjs') && packaging.includes('audit-release-owner-action-plan.mjs'), 'references/packaging.md'),
109
+ check('ROAP11', 'validator includes release owner action plan audit', validate.includes('audit-release-owner-action-plan.mjs'), 'scripts/validate-gse.mjs'),
110
+ check('ROAP12', 'release bundle includes owner action plan', releaseGenerator.includes('release-owner-action-plan.md') && releaseAudit.includes('release-owner-action-plan.md'), 'release bundle generator and audit'),
111
+ check('ROAP13', 'plan verification commands use shell-safe placeholders', planVerificationCommandsAreShellSafe, 'verification commands use __GSE__ instead of <gse>'),
112
+ check('ROAP14', 'canonical release owner action plan matches current manifest counts and pending gates', canonicalPlanMatchesCurrentManifest, '.gse/acceptance/release-owner-action-plan.md'),
113
+ ]
114
+
115
+ const passed = checks.filter((item) => item.status === 'passed').length
116
+ const failed = checks.length - passed
117
+ const report = {
118
+ root,
119
+ generatedAt: new Date().toISOString(),
120
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
121
+ workflows: {
122
+ releaseOwnerActionPlan: failed === 0 ? 'verified' : 'failed',
123
+ publicAccepted: manifest?.publicAcceptance?.publicAccepted ?? 'unknown',
124
+ pendingGates: pendingGates.length,
125
+ },
126
+ limits: [
127
+ 'This audit verifies generation of an owner-facing action plan from the release status manifest.',
128
+ 'It does not create owner decisions, public CI, public repository settings, marketplace approval, registry publication, or native slash-command evidence.',
129
+ ],
130
+ checks,
131
+ }
132
+
133
+ function renderMarkdown(data) {
134
+ const lines = []
135
+ lines.push('# GSE Release Owner Action Plan Audit')
136
+ lines.push('')
137
+ lines.push('Generated: ' + data.generatedAt)
138
+ lines.push('Root: ' + data.root)
139
+ lines.push('')
140
+ lines.push('## Summary')
141
+ lines.push('')
142
+ lines.push('- Status: ' + data.summary.status)
143
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
144
+ lines.push('- Release owner action plan: ' + data.workflows.releaseOwnerActionPlan)
145
+ lines.push('- Public accepted: ' + data.workflows.publicAccepted)
146
+ lines.push('- Pending gates: ' + data.workflows.pendingGates)
147
+ lines.push('')
148
+ lines.push('## Checks')
149
+ lines.push('')
150
+ for (const item of data.checks) {
151
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
152
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
153
+ }
154
+ lines.push('')
155
+ lines.push('## Limits')
156
+ lines.push('')
157
+ for (const item of data.limits) lines.push('- ' + item)
158
+ return lines.join('\n') + '\n'
159
+ }
160
+
161
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
162
+ else console.log(renderMarkdown(report))
163
+
164
+ if (failed > 0) process.exit(1)
@@ -0,0 +1,106 @@
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 skill = read('SKILL.md')
30
+ const packaging = read('references/packaging.md')
31
+ const release = read('references/release.md')
32
+ const publicRelease = read('references/public-release.md')
33
+ const quality = read('references/quality-gates.md')
34
+ const openai = read('agents/openai.yaml')
35
+ const validate = read('scripts/validate-gse.mjs')
36
+
37
+ const packageBoundary = ['SKILL.md', 'CHANGELOG.md', 'CONTRIBUTING.md', 'SECURITY.md', 'SUPPORT.md', 'references/', 'scripts/', 'assets/templates/', 'assets/marketplace/', 'examples/', 'agents/openai.yaml', '.gse/', '.learnings/']
38
+ const releaseNoteFields = ['Release label:', 'Date:', 'Readiness:', 'Changed:', 'Validation:', 'Compatibility impact:', 'Migration or rollback:', 'Known risks:', 'Follow-up slices:']
39
+ const handoffFields = ['Skill path:', 'Release label or date.', 'Validation command and latest result.', 'Evidence log path.', 'Known residual risks.', 'Next slice from `.gse/current-slice.md`.']
40
+
41
+ const checks = [
42
+ check('R01', 'packaging reference exists', exists('references/packaging.md'), 'references/packaging.md'),
43
+ check('R02', 'SKILL routes packaging reference', skill.includes('references/packaging.md'), 'SKILL.md Reference Routing'),
44
+ check('R03', 'package boundary lists core skill artifacts', packageBoundary.every((item) => packaging.includes(item)), packageBoundary.join(', ')),
45
+ check('R04', 'validation command is the release gate', packaging.includes('node <skill>/scripts/validate-gse.mjs --root <skill>') && quality.includes('Use `references/release.md`') && release.includes('references/quality-gates.md'), 'packaging, quality, and release references'),
46
+ check('R05', 'release label policy is explicit without fake semver', packaging.includes('gse-internal-YYYY-MM-DD-N') && packaging.includes('Use semver only after there is a maintained distribution channel'), 'internal release label policy'),
47
+ check('R06', 'release notes fields are complete', releaseNoteFields.every((item) => packaging.includes(item)), releaseNoteFields.join(', ')),
48
+ check('R07', 'install/update handoff fields are complete', handoffFields.every((item) => packaging.includes(item)), 'handoff checklist'),
49
+ check('R08', 'rollback guidance distinguishes low-risk and generated artifacts', packaging.includes('file-level revert') && packaging.includes('generated files or adapters') && packaging.includes('re-running `validate-gse.mjs`'), 'rollback section'),
50
+ check('R09', 'readiness status avoids overstating acceptance', packaging.includes('Do not call a release accepted only because local validation passed') && packaging.includes('true fresh-session acceptance separate from fresh-session readiness'), 'readiness status and release notes rules'),
51
+ check('R10', 'host UI metadata is present and minimal', openai.includes('display_name: "GSE"') && openai.includes('short_description') && openai.includes('default_prompt'), 'agents/openai.yaml'),
52
+ check('R11', 'consolidated validator includes packaging-adjacent gates', validate.includes('audit-fresh-session-readiness.mjs') && validate.includes('audit-compatibility.mjs') && validate.includes('audit-marketplace-discovery.mjs') && validate.includes('audit-host-ui-invocation.mjs') && validate.includes('quick_validate.py'), 'scripts/validate-gse.mjs'),
53
+ check('R12', 'no external distribution is claimed', packaging.includes('not a registry publication process') && packaging.includes('Do not claim marketplace distribution') && packaging.includes('Do not call a release accepted'), 'distribution boundary'),
54
+ check('R13', 'public release metadata gate is linked', release.includes('references/public-release.md') && packaging.includes('references/public-release.md') && publicRelease.includes('owner-required') && publicRelease.includes('assets/templates/public-release-record.md'), 'release, packaging, public-release references'),
55
+ check('R14', 'release docs include npm publish dry-run preflight', packaging.includes('audit-npm-publish-dry-run.mjs') && packaging.includes('harmful metadata auto-correction warnings') && validate.includes('audit-npm-publish-dry-run.mjs'), 'references/packaging.md, scripts/validate-gse.mjs'),
56
+ ]
57
+
58
+ const passed = checks.filter((item) => item.status === 'passed').length
59
+ const failed = checks.length - passed
60
+ const report = {
61
+ root,
62
+ generatedAt: new Date().toISOString(),
63
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
64
+ workflows: { releasePackagingReadiness: failed === 0 ? 'verified' : 'failed' },
65
+ releaseReadiness: failed === 0 ? 'verified' : 'result',
66
+ acceptedBy: 'not accepted; this audit verifies release packaging readiness but does not publish or owner-accept a release',
67
+ limits: [
68
+ 'Release readiness audit verifies packaging policy, validation gate, handoff fields, rollback guidance, and metadata presence.',
69
+ 'It does not publish GSE, install it in another host, run marketplace checks, or mark v1.0 complete.',
70
+ 'A real release still needs the project or owner policy required for accepted status.',
71
+ ],
72
+ checks,
73
+ }
74
+
75
+ function renderMarkdown(data) {
76
+ const lines = []
77
+ lines.push('# GSE Release Readiness Audit')
78
+ lines.push('')
79
+ lines.push('Generated: ' + data.generatedAt)
80
+ lines.push('Root: ' + data.root)
81
+ lines.push('')
82
+ lines.push('## Summary')
83
+ lines.push('')
84
+ lines.push('- Status: ' + data.summary.status)
85
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
86
+ lines.push('- Release packaging readiness: ' + data.workflows.releasePackagingReadiness)
87
+ lines.push('- Release readiness: ' + data.releaseReadiness)
88
+ lines.push('- Accepted by: ' + data.acceptedBy)
89
+ lines.push('')
90
+ lines.push('## Checks')
91
+ lines.push('')
92
+ for (const item of data.checks) {
93
+ const marker = item.status === 'passed' ? '[x]' : '[ ]'
94
+ lines.push('- ' + marker + ' ' + item.id + ' ' + item.label + ': ' + item.evidence)
95
+ }
96
+ lines.push('')
97
+ lines.push('## Limits')
98
+ lines.push('')
99
+ for (const item of data.limits) lines.push('- ' + item)
100
+ return lines.join('\n') + '\n'
101
+ }
102
+
103
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
104
+ else console.log(renderMarkdown(report))
105
+
106
+ if (failed > 0) process.exit(1)