@t275005746/gse 0.1.1 → 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 (84) hide show
  1. package/.gse/state.json +147 -26
  2. package/CHANGELOG.md +19 -3
  3. package/README.md +13 -6
  4. package/README.zh-CN.md +13 -6
  5. package/SKILL.md +32 -12
  6. package/assets/templates/dispatch-packet.md +22 -14
  7. package/assets/templates/evidence.md +11 -5
  8. package/assets/templates/role-fallback-packet.md +49 -0
  9. package/package.json +18 -10
  10. package/references/agent-roles.md +41 -20
  11. package/references/commands.md +74 -45
  12. package/references/drift-audit.md +2 -1
  13. package/references/evidence-taxonomy.md +46 -9
  14. package/references/file-ownership.md +17 -13
  15. package/references/final-form-roadmap.md +201 -0
  16. package/references/final-readiness.md +3 -3
  17. package/references/host-adapters.md +38 -10
  18. package/references/learning-system.md +24 -8
  19. package/references/maintenance-cadence.md +51 -0
  20. package/references/project-guards.md +52 -0
  21. package/references/quality-gates.md +18 -11
  22. package/references/role-dispatch-fallback.md +54 -0
  23. package/references/tool-adapters.md +13 -3
  24. package/scripts/audit-close-gate-hardening.mjs +188 -0
  25. package/scripts/audit-close-gate.mjs +219 -33
  26. package/scripts/audit-command-execution.mjs +30 -17
  27. package/scripts/audit-commands.mjs +7 -5
  28. package/scripts/audit-completion-plan-drill.mjs +230 -0
  29. package/scripts/audit-completion-readiness.mjs +9 -6
  30. package/scripts/audit-continue-preflight.mjs +234 -0
  31. package/scripts/audit-evidence-levels.mjs +217 -0
  32. package/scripts/audit-evidence-review-queue.mjs +206 -0
  33. package/scripts/audit-final-acceptance-packet.mjs +9 -9
  34. package/scripts/audit-final-form-progress-report.mjs +19 -18
  35. package/scripts/audit-final-form-roadmap.mjs +157 -0
  36. package/scripts/audit-final-form-stale-copy.mjs +2 -2
  37. package/scripts/audit-final-readiness.mjs +3 -3
  38. package/scripts/audit-fresh-session-readiness.mjs +1 -1
  39. package/scripts/audit-host-capabilities.mjs +237 -0
  40. package/scripts/audit-installed-sync.mjs +203 -0
  41. package/scripts/audit-learning-drift.mjs +292 -0
  42. package/scripts/audit-learning-promotion.mjs +351 -0
  43. package/scripts/audit-learning-system.mjs +24 -14
  44. package/scripts/audit-local-final-form-completion.mjs +11 -10
  45. package/scripts/audit-maintenance-cadence.mjs +139 -0
  46. package/scripts/audit-maintenance-snapshot.mjs +181 -0
  47. package/scripts/audit-npm-package-metadata.mjs +8 -2
  48. package/scripts/audit-npm-publish-dry-run.mjs +10 -4
  49. package/scripts/audit-npm-tarball-install.mjs +9 -3
  50. package/scripts/audit-owner-external-gate-kit.mjs +12 -11
  51. package/scripts/audit-project-guards.mjs +189 -0
  52. package/scripts/audit-project.mjs +14 -11
  53. package/scripts/audit-public-acceptance-handoff.mjs +10 -10
  54. package/scripts/audit-public-acceptance-readiness.mjs +6 -6
  55. package/scripts/audit-public-release-checklist.mjs +17 -15
  56. package/scripts/audit-release-bundle.mjs +13 -11
  57. package/scripts/audit-release-owner-action-plan-drill.mjs +5 -4
  58. package/scripts/audit-release-owner-action-plan.mjs +10 -10
  59. package/scripts/audit-release-status-manifest.mjs +4 -4
  60. package/scripts/audit-roadmap-consistency.mjs +11 -7
  61. package/scripts/audit-role-dispatch-fallback.mjs +212 -0
  62. package/scripts/audit-session-sync.mjs +127 -0
  63. package/scripts/audit-state-freshness.mjs +6 -5
  64. package/scripts/audit-state-repair.mjs +360 -0
  65. package/scripts/audit-target-hardening-drills.mjs +267 -0
  66. package/scripts/audit-tool-fallback-policy.mjs +180 -0
  67. package/scripts/audit-ui-browser-evidence-policy.mjs +191 -0
  68. package/scripts/audit-validation-profiles.mjs +6 -4
  69. package/scripts/backfill-evidence-levels.mjs +98 -0
  70. package/scripts/check-encoding.mjs +72 -0
  71. package/scripts/generate-continue-packet.mjs +1214 -0
  72. package/scripts/generate-final-acceptance-packet.mjs +23 -8
  73. package/scripts/generate-final-form-progress-report.mjs +25 -23
  74. package/scripts/generate-host-runtime-evidence-handoff.mjs +23 -16
  75. package/scripts/generate-maintenance-snapshot.mjs +216 -0
  76. package/scripts/generate-public-acceptance-handoff.mjs +26 -14
  77. package/scripts/generate-release-owner-action-plan.mjs +4 -3
  78. package/scripts/generate-release-status-manifest.mjs +4 -3
  79. package/scripts/init-project.mjs +144 -63
  80. package/scripts/record-learning.mjs +37 -8
  81. package/scripts/record-session-sync.mjs +87 -0
  82. package/scripts/run-gse-command.mjs +79 -47
  83. package/scripts/run-validation-profile.mjs +24 -5
  84. package/scripts/validate-gse.mjs +216 -0
@@ -0,0 +1,230 @@
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) {
19
+ const result = spawnSync(command, commandArgs, { cwd, encoding: 'utf8', windowsHide: true })
20
+ return {
21
+ command: [command, ...commandArgs].join(' '),
22
+ status: result.status ?? 1,
23
+ stdout: (result.stdout ?? '').trim(),
24
+ stderr: (result.stderr ?? '').trim(),
25
+ }
26
+ }
27
+
28
+ function parseJson(text) {
29
+ try { return JSON.parse(text) } catch { return null }
30
+ }
31
+
32
+ function check(id, label, ok, evidence, risk = '') {
33
+ return { id, label, status: ok ? 'passed' : 'failed', evidence, risk }
34
+ }
35
+
36
+ function write(filePath, text) {
37
+ fs.mkdirSync(path.dirname(filePath), { recursive: true })
38
+ fs.writeFileSync(filePath, text, 'utf8')
39
+ }
40
+
41
+ function createFixture() {
42
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-completion-plan-drill-'))
43
+ write(path.join(dir, 'package.json'), JSON.stringify({ scripts: { 'check:encoding': 'node scripts/check-encoding.mjs' } }, null, 2) + '\n')
44
+ write(path.join(dir, 'scripts', 'run-gse-command.mjs'), '#!/usr/bin/env node\n')
45
+ write(path.join(dir, 'scripts', 'check-encoding.mjs'), '#!/usr/bin/env node\n')
46
+ write(path.join(dir, 'references', 'final-readiness.md'), '# Final Readiness\n')
47
+ write(path.join(dir, 'docs', 'productization-architecture.md'), '# Productization\n')
48
+ write(path.join(dir, '.gse', 'README.md'), '# GSE\n')
49
+ write(path.join(dir, '.gse', 'project-profile.md'), '# Project Profile\n\n- Product/system name: Completion Plan Fixture\n')
50
+ write(path.join(dir, '.gse', 'goal-map.md'), '# Goal Map\n\n- Active slice: Completion plan fixture.\n- Next action: Run completion plan drill.\n')
51
+ write(path.join(dir, '.gse', 'quality-gates.md'), '# Quality Gates\n\n- Evidence required.\n')
52
+ write(path.join(dir, '.gse', 'session-sync.jsonl'), '')
53
+ write(path.join(dir, '.gse', 'state.json'), JSON.stringify({
54
+ schemaVersion: 1,
55
+ projectName: 'completion-plan-fixture',
56
+ mode: 'standard',
57
+ canonicalPlan: 'docs/productization-architecture.md',
58
+ phase: 'execute',
59
+ currentSlice: {
60
+ id: 'completion-plan-fixture',
61
+ outcome: 'Completion plan fixture.',
62
+ status: 'planned',
63
+ nextAction: 'Run completion plan drill.',
64
+ },
65
+ toolStatuses: { browser: 'unknown', lsp: 'unknown', mcp: 'unknown', subagents: 'unknown', ci: 'unknown' },
66
+ lastEvidence: '.gse/evidence/2026-07-09.md',
67
+ residualRisks: [],
68
+ }, null, 2) + '\n')
69
+ write(path.join(dir, '.gse', 'evidence', 'index.jsonl'), JSON.stringify({
70
+ date: '2026-07-09',
71
+ recordType: 'slice',
72
+ status: 'verified',
73
+ evidenceLevel: 'verified-unit',
74
+ requiredEvidenceLevel: 'verified-unit',
75
+ summary: 'Completion plan fixture evidence.',
76
+ evidenceFile: '.gse/evidence/2026-07-09.md',
77
+ commands: ['fixture'],
78
+ nextAction: 'Run completion plan drill.',
79
+ }) + '\n')
80
+ write(path.join(dir, '.gse', 'evidence', '2026-07-09.md'), '# Evidence\n')
81
+ write(path.join(dir, '.gse', 'maintenance', 'latest-maintenance-snapshot.json'), JSON.stringify({
82
+ schemaVersion: 1,
83
+ root: dir,
84
+ target: dir,
85
+ generatedAt: '2026-07-09T00:00:00.000Z',
86
+ summary: { status: 'passed', passed: 9, failed: 0, total: 9, installedSyncMode: 'verified', releaseBundleChecked: true },
87
+ workflows: { maintenanceSnapshot: 'verified', installedSync: 'verified', releaseBundleFreshness: 'verified' },
88
+ results: [],
89
+ }, null, 2) + '\n')
90
+
91
+ run('git', ['init'], dir)
92
+ run('git', ['config', 'user.email', 'gse-fixture@example.invalid'], dir)
93
+ run('git', ['config', 'user.name', 'GSE Fixture'], dir)
94
+ run('git', ['add', '.'], dir)
95
+ run('git', ['commit', '-m', 'baseline'], dir)
96
+ return dir
97
+ }
98
+
99
+ function continuePacket(target) {
100
+ const result = run(process.execPath, [path.join(root, 'scripts', 'generate-continue-packet.mjs'), '--root', root, '--target', target, '--json'], root)
101
+ return { result, data: parseJson(result.stdout) }
102
+ }
103
+
104
+ function activeIds(data) {
105
+ return (data?.compactState?.completionPlan?.conditionalCloseCommands ?? [])
106
+ .filter((item) => item.active)
107
+ .map((item) => item.id)
108
+ .sort()
109
+ }
110
+
111
+ function hasExactly(data, expected) {
112
+ const actual = activeIds(data)
113
+ const sortedExpected = [...expected].sort()
114
+ return actual.length === sortedExpected.length && actual.every((item, index) => item === sortedExpected[index])
115
+ }
116
+
117
+ function drill(label, mutate, expectedActiveIds) {
118
+ const fixture = createFixture()
119
+ try {
120
+ if (mutate) mutate(fixture)
121
+ const { result, data } = continuePacket(fixture)
122
+ return {
123
+ label,
124
+ command: result.command,
125
+ status: result.status,
126
+ expectedActiveIds: [...expectedActiveIds].sort(),
127
+ actualActiveIds: activeIds(data),
128
+ activeCommands: data?.compactState?.completionPlan?.activeCloseCommands ?? [],
129
+ changedPaths: data?.compactState?.completionPlan?.changedPaths ?? [],
130
+ ignoredGeneratedPaths: data?.compactState?.completionPlan?.ignoredGeneratedPaths ?? [],
131
+ ignoredGeneratedPathCount: data?.compactState?.completionPlan?.ignoredGeneratedPathCount ?? 0,
132
+ ok: result.status === 0 && hasExactly(data, expectedActiveIds),
133
+ }
134
+ } finally {
135
+ fs.rmSync(fixture, { recursive: true, force: true })
136
+ }
137
+ }
138
+
139
+ const drills = [
140
+ drill('clean worktree activates no conditionals', null, []),
141
+ drill('docs change activates encoding only', (dir) => { write(path.join(dir, 'docs', 'usage.md'), '# Usage\n') }, ['encoding']),
142
+ drill('script capability change activates installed sync, maintenance, and session sync', (dir) => { write(path.join(dir, 'scripts', 'new-capability.mjs'), '#!/usr/bin/env node\n') }, ['installed-sync', 'maintenance-snapshot', 'session-sync']),
143
+ drill('reference change activates docs, capability, release, maintenance, and session sync checks', (dir) => { write(path.join(dir, 'references', 'new-reference.md'), '# Reference\n') }, ['encoding', 'installed-sync', 'maintenance-snapshot', 'release-bundle', 'session-sync']),
144
+ drill('public acceptance change activates encoding, release bundle, and maintenance only', (dir) => { write(path.join(dir, '.gse', 'acceptance', 'new-acceptance.md'), '# Acceptance\n') }, ['encoding', 'maintenance-snapshot', 'release-bundle']),
145
+ drill('evidence index change activates encoding only', (dir) => {
146
+ fs.appendFileSync(path.join(dir, '.gse', 'evidence', 'index.jsonl'), JSON.stringify({
147
+ date: '2026-07-09',
148
+ recordType: 'drill',
149
+ status: 'verified',
150
+ evidenceLevel: 'verified-unit',
151
+ requiredEvidenceLevel: 'verified-unit',
152
+ summary: 'Additional drill evidence.',
153
+ evidenceFile: '.gse/evidence/2026-07-09.md',
154
+ commands: ['fixture'],
155
+ nextAction: 'Continue drill.',
156
+ }) + '\n', 'utf8')
157
+ }, ['encoding']),
158
+ drill('untracked generated artifacts stay visible but activate no conditionals', (dir) => {
159
+ write(path.join(dir, 'node_modules', '.bin', 'tool'), '')
160
+ write(path.join(dir, 'pnpm-lock.yaml'), 'lockfileVersion: 9.0\n')
161
+ }, []),
162
+ drill('tracked lockfile change remains actionable', (dir) => {
163
+ write(path.join(dir, 'pnpm-lock.yaml'), 'lockfileVersion: 9.0\n')
164
+ run('git', ['add', 'pnpm-lock.yaml'], dir)
165
+ run('git', ['commit', '-m', 'add tracked lockfile'], dir)
166
+ write(path.join(dir, 'pnpm-lock.yaml'), 'lockfileVersion: 9.0\nsettings:\n strictPeerDependencies: false\n')
167
+ }, ['encoding']),
168
+ ]
169
+
170
+ const checks = [
171
+ check('CPD01', 'clean worktree does not falsely activate conditional close commands', drills[0].ok, drills[0].actualActiveIds.join(',') || 'none'),
172
+ check('CPD02', 'docs-only dirty worktree activates encoding only', drills[1].ok, `actual=${drills[1].actualActiveIds.join(',') || 'none'}`),
173
+ check('CPD03', 'script capability changes activate installed-sync, maintenance, and session-sync without encoding', drills[2].ok, `actual=${drills[2].actualActiveIds.join(',') || 'none'}`),
174
+ check('CPD04', 'reference changes activate all relevant docs/capability/release close checks', drills[3].ok, `actual=${drills[3].actualActiveIds.join(',') || 'none'}`),
175
+ check('CPD05', 'public acceptance changes activate release checks without installed/session sync', drills[4].ok, `actual=${drills[4].actualActiveIds.join(',') || 'none'}`),
176
+ check('CPD06', 'evidence index changes activate encoding without release/capability checks', drills[5].ok, `actual=${drills[5].actualActiveIds.join(',') || 'none'}`),
177
+ check('CPD07', 'generated/noisy untracked paths do not activate conditional close commands', drills[6].ok && drills[6].changedPaths.length === 0 && drills[6].ignoredGeneratedPathCount >= 2, `actual=${drills[6].actualActiveIds.join(',') || 'none'} ignored=${drills[6].ignoredGeneratedPaths.join(',') || 'none'}`),
178
+ check('CPD08', 'tracked lockfile changes remain actionable and can trigger configured close checks', drills[7].ok && drills[7].changedPaths.includes('pnpm-lock.yaml') && drills[7].ignoredGeneratedPathCount === 0, `actual=${drills[7].actualActiveIds.join(',') || 'none'} changed=${drills[7].changedPaths.join(',') || 'none'}`),
179
+ check('CPD09', 'non-release capability maintenance uses skip-release-bundle', drills[2].activeCommands.some((item) => item.includes('generate-maintenance-snapshot.mjs') && item.includes('--skip-release-bundle')), drills[2].activeCommands.join(' | ')),
180
+ check('CPD10', 'release-sensitive maintenance keeps full release bundle freshness', drills[3].activeCommands.some((item) => item.includes('generate-maintenance-snapshot.mjs') && !item.includes('--skip-release-bundle')), drills[3].activeCommands.join(' | ')),
181
+ ]
182
+
183
+ const passed = checks.filter((item) => item.status === 'passed').length
184
+ const failed = checks.length - passed
185
+ const report = {
186
+ root,
187
+ generatedAt: new Date().toISOString(),
188
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
189
+ workflows: {
190
+ completionPlanDrill: failed === 0 ? 'verified' : 'failed',
191
+ cleanWorktreeFalsePositiveGuard: drills[0].ok ? 'verified' : 'failed',
192
+ dirtyWorktreeConditionalRouting: failed === 0 ? 'verified' : 'failed',
193
+ },
194
+ drills,
195
+ checks,
196
+ limits: [
197
+ 'This audit verifies portable /gse continue completionPlan routing in temporary git fixtures.',
198
+ 'It does not execute the close commands; it verifies whether the correct commands become active for each worktree state.',
199
+ 'Native host slash-command behavior remains a host-specific adapter claim and is not covered by this drill.',
200
+ ],
201
+ }
202
+
203
+ function renderMarkdown(data) {
204
+ const lines = []
205
+ lines.push('# GSE Completion Plan Drill Audit')
206
+ lines.push('')
207
+ lines.push('Generated: ' + data.generatedAt)
208
+ lines.push('Root: ' + data.root)
209
+ lines.push('')
210
+ lines.push('## Summary')
211
+ lines.push('')
212
+ lines.push('- Status: ' + data.summary.status)
213
+ lines.push('- Checks: ' + data.summary.passed + '/' + data.summary.total)
214
+ lines.push('')
215
+ lines.push('## Drills')
216
+ lines.push('')
217
+ for (const item of data.drills) {
218
+ lines.push('- ' + (item.ok ? '[x]' : '[ ]') + ' ' + item.label + ': expected `' + item.expectedActiveIds.join(',') + '`, actual `' + item.actualActiveIds.join(',') + '`')
219
+ }
220
+ lines.push('')
221
+ lines.push('## Limits')
222
+ lines.push('')
223
+ for (const item of data.limits) lines.push('- ' + item)
224
+ return lines.join('\n') + '\n'
225
+ }
226
+
227
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
228
+ else console.log(renderMarkdown(report))
229
+
230
+ if (failed > 0) process.exit(1)
@@ -100,8 +100,9 @@ const localCapabilityAudits = [
100
100
  'audit-release-owner-action-plan.mjs',
101
101
  'audit-public-release-checklist.mjs',
102
102
  'audit-release-owner-action-plan-drill.mjs',
103
- 'audit-final-form-progress-report.mjs',
104
- 'audit-local-final-form-completion.mjs',
103
+ 'audit-final-form-progress-report.mjs',
104
+ 'audit-final-form-roadmap.mjs',
105
+ 'audit-local-final-form-completion.mjs',
105
106
  'audit-final-form-stale-copy.mjs',
106
107
  'audit-npm-tarball-install.mjs',
107
108
  'audit-npm-publish-dry-run.mjs',
@@ -206,9 +207,11 @@ const requiredArtifacts = [
206
207
  'scripts/generate-public-release-checklist.mjs',
207
208
  'scripts/audit-public-release-checklist.mjs',
208
209
  'scripts/audit-release-owner-action-plan-drill.mjs',
209
- 'scripts/generate-final-form-progress-report.mjs',
210
- 'scripts/audit-final-form-progress-report.mjs',
211
- 'scripts/audit-local-final-form-completion.mjs',
210
+ 'scripts/generate-final-form-progress-report.mjs',
211
+ 'scripts/audit-final-form-progress-report.mjs',
212
+ 'references/final-form-roadmap.md',
213
+ 'scripts/audit-final-form-roadmap.mjs',
214
+ 'scripts/audit-local-final-form-completion.mjs',
212
215
  'scripts/audit-final-form-stale-copy.mjs',
213
216
  'scripts/audit-npm-tarball-install.mjs',
214
217
  'scripts/audit-npm-publish-dry-run.mjs',
@@ -240,7 +243,7 @@ const checks = [
240
243
  check('CR05', 'current slice preserves required GSE slice fields after acceptance', currentSlice.includes('## Outcome') && currentSlice.includes('## Scope') && currentSlice.includes('## Acceptance') && currentSlice.includes('## Evidence Plan') && currentSlice.includes('## Risk') && currentSlice.includes('## Next Action'), '.gse/current-slice.md'),
241
244
  check('CR06', 'goal map records v1 execution-state work as verified', goalMap.includes('GSE-008') && goalMap.includes('Productize v1.0 execution-state workflow') && goalMap.includes('verified') && goalMap.includes('audit-v1-target-validation.mjs'), '.gse/goal-map.md'),
242
245
  check('CR07', 'evidence log records owner-approved external acceptance', ownerAcceptanceRecorded, '.gse/evidence/2026-07-05.md'),
243
- check('CR08', 'final-form limits are explicit after current scope can be claimed', masterPlan.includes('Remaining final-form work is host-native slash-command support with real host runtime evidence.') && goalMap.includes('Final-form gaps'), 'control docs keep final-form limits scoped'),
246
+ check('CR08', 'final-form limits are explicit after current scope can be claimed', masterPlan.includes('The Final Form Roadmap now lives in `references/final-form-roadmap.md`') && masterPlan.includes('live claim boundary') && (goalMap.includes('Native slash command') || goalMap.includes('host-native slash-command support')) && goalMap.includes('Final-form gaps'), 'control docs keep final-form limits scoped'),
244
247
  ]
245
248
 
246
249
  const passed = checks.filter((item) => item.status === 'passed').length
@@ -0,0 +1,234 @@
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(script, commandArgs) {
19
+ const result = spawnSync(process.execPath, [path.join(root, 'scripts', script), ...commandArgs], {
20
+ cwd: root,
21
+ encoding: 'utf8',
22
+ windowsHide: true,
23
+ })
24
+ return {
25
+ command: [process.execPath, path.join(root, 'scripts', script), ...commandArgs].join(' '),
26
+ status: result.status ?? 1,
27
+ stdout: (result.stdout ?? '').trim(),
28
+ stderr: (result.stderr ?? '').trim(),
29
+ }
30
+ }
31
+
32
+ function parseJson(text) {
33
+ try {
34
+ return JSON.parse(text)
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 fixture(invalidEvidence = false) {
45
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gse-continue-audit-'))
46
+ fs.mkdirSync(path.join(dir, '.gse', 'evidence'), { recursive: true })
47
+ fs.mkdirSync(path.join(dir, '.gse', 'maintenance'), { recursive: true })
48
+ fs.mkdirSync(path.join(dir, 'scripts'), { recursive: true })
49
+ fs.mkdirSync(path.join(dir, 'references'), { recursive: true })
50
+ fs.mkdirSync(path.join(dir, 'docs'), { recursive: true })
51
+ fs.writeFileSync(path.join(dir, '.gse', 'README.md'), '# GSE\n', 'utf8')
52
+ fs.writeFileSync(path.join(dir, '.gse', 'project-profile.md'), '# Project Profile\n\n- Product/system name: Continue Fixture\n', 'utf8')
53
+ fs.writeFileSync(path.join(dir, '.gse', 'goal-map.md'), '# Goal Map\n\n- Active slice: Continue fixture.\n- Next action: Run continue audit.\n', 'utf8')
54
+ fs.writeFileSync(path.join(dir, '.gse', 'quality-gates.md'), '# Quality Gates\n\n- Evidence required.\n', 'utf8')
55
+ fs.writeFileSync(path.join(dir, '.gse', 'session-sync.jsonl'), '', 'utf8')
56
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ scripts: { 'check:encoding': 'node scripts/check-encoding.mjs' } }, null, 2) + '\n', 'utf8')
57
+ fs.writeFileSync(path.join(dir, 'scripts', 'run-gse-command.mjs'), '#!/usr/bin/env node\n', 'utf8')
58
+ fs.writeFileSync(path.join(dir, 'references', 'final-readiness.md'), '# Final Readiness\n', 'utf8')
59
+ fs.writeFileSync(path.join(dir, 'docs', 'productization-architecture.md'), '# Productization\n', 'utf8')
60
+ fs.writeFileSync(path.join(dir, '.gse', 'state.json'), JSON.stringify({
61
+ schemaVersion: 1,
62
+ projectName: 'continue-fixture',
63
+ mode: 'standard',
64
+ canonicalPlan: 'docs/productization-architecture.md',
65
+ phase: 'execute',
66
+ currentSlice: {
67
+ id: 'continue-fixture',
68
+ outcome: 'Continue fixture.',
69
+ status: 'planned',
70
+ nextAction: 'Run continue audit.',
71
+ },
72
+ toolStatuses: {
73
+ browser: 'unknown',
74
+ lsp: 'unknown',
75
+ mcp: 'unknown',
76
+ subagents: 'unknown',
77
+ ci: 'unknown',
78
+ },
79
+ lastEvidence: '.gse/evidence/2026-07-08.md',
80
+ residualRisks: ['risk one', 'risk two', 'risk three', 'risk four'],
81
+ riskArchive: [
82
+ {
83
+ archivedAt: '2026-07-08',
84
+ risk: 'archived risk',
85
+ resolution: 'fixture resolution',
86
+ },
87
+ ],
88
+ }, null, 2) + '\n', 'utf8')
89
+ fs.writeFileSync(
90
+ path.join(dir, '.gse', 'evidence', 'index.jsonl'),
91
+ invalidEvidence
92
+ ? '{"date":"2026-07-08"\n'
93
+ : JSON.stringify({
94
+ date: '2026-07-08',
95
+ recordType: 'slice',
96
+ status: 'verified',
97
+ evidenceLevel: 'verified-unit',
98
+ requiredEvidenceLevel: 'verified-unit',
99
+ summary: 'Continue fixture evidence.',
100
+ evidenceFile: '.gse/evidence/2026-07-08.md',
101
+ commands: ['fixture'],
102
+ nextAction: 'Run continue audit.',
103
+ }) + '\n',
104
+ 'utf8',
105
+ )
106
+ fs.writeFileSync(path.join(dir, '.gse', 'evidence', '2026-07-08.md'), '# Evidence\n', 'utf8')
107
+ fs.writeFileSync(path.join(dir, '.gse', 'maintenance', 'latest-maintenance-snapshot.json'), JSON.stringify({
108
+ schemaVersion: 1,
109
+ root: dir,
110
+ target: dir,
111
+ installedRoot: null,
112
+ generatedAt: '2026-07-08T00:00:00.000Z',
113
+ summary: {
114
+ status: 'passed',
115
+ passed: 9,
116
+ failed: 0,
117
+ total: 9,
118
+ installedSyncMode: 'package-only',
119
+ releaseBundleChecked: false,
120
+ },
121
+ workflows: {
122
+ maintenanceSnapshot: 'verified',
123
+ installedSync: 'package-only',
124
+ releaseBundleFreshness: 'skipped',
125
+ },
126
+ results: [],
127
+ }, null, 2) + '\n', 'utf8')
128
+ spawnSync('git', ['init'], { cwd: dir, encoding: 'utf8', windowsHide: true })
129
+ return dir
130
+ }
131
+
132
+ function verifiedSliceFixture() {
133
+ const dir = fixture(false)
134
+ const statePath = path.join(dir, '.gse', 'state.json')
135
+ const goalMapPath = path.join(dir, '.gse', 'goal-map.md')
136
+ const state = JSON.parse(fs.readFileSync(statePath, 'utf8'))
137
+ state.currentSlice.status = 'verified'
138
+ state.currentSlice.nextAction = 'Open the next fixture slice with a deliberately long machine-readable reason that should remain available to successor agents even when the display reason is compacted for the short entry prompt and JSON packet overview.'
139
+ state.residualRisks = [
140
+ 'A deliberately long actionable risk should become the first next-slice candidate when the current next action is only a meta instruction, because successor agents need concrete work instead of a process reminder.',
141
+ ]
142
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n', 'utf8')
143
+ fs.writeFileSync(goalMapPath, '# Goal Map\n\n- Active slice: Continue fixture verified.\n- Next action: Open the next fixture slice with a deliberately long machine-readable reason that should remain available to successor agents even when the display reason is compacted for the short entry prompt and JSON packet overview.\n', 'utf8')
144
+ return dir
145
+ }
146
+
147
+ const validFixture = fixture(false)
148
+ const invalidFixture = fixture(true)
149
+ const verifiedFixture = verifiedSliceFixture()
150
+ const directValid = run('generate-continue-packet.mjs', ['--root', root, '--target', validFixture, '--json'])
151
+ const directInvalid = run('generate-continue-packet.mjs', ['--root', root, '--target', invalidFixture, '--json'])
152
+ const directVerified = run('generate-continue-packet.mjs', ['--root', root, '--target', verifiedFixture, '--json'])
153
+ const commandValid = run('run-gse-command.mjs', ['--root', root, '--target', validFixture, '--command', '/gse continue', '--json'])
154
+ const commandCompact = run('run-gse-command.mjs', ['--root', root, '--target', validFixture, '--command', '/gse continue', '--json', '--compact'])
155
+ const commandInvalid = run('run-gse-command.mjs', ['--root', root, '--target', invalidFixture, '--command', '/gse continue', '--json'])
156
+ const gseSelf = run('run-gse-command.mjs', ['--root', root, '--target', root, '--command', '/gse continue', '--json', '--compact'])
157
+
158
+ const validData = parseJson(directValid.stdout)
159
+ const invalidData = parseJson(directInvalid.stdout)
160
+ const verifiedData = parseJson(directVerified.stdout)
161
+ const commandValidData = parseJson(commandValid.stdout)
162
+ const commandCompactData = parseJson(commandCompact.stdout)
163
+ const commandInvalidData = parseJson(commandInvalid.stdout)
164
+ const gseSelfData = parseJson(gseSelf.stdout)
165
+ const runnerSource = fs.readFileSync(path.join(root, 'scripts', 'run-gse-command.mjs'), 'utf8')
166
+ const skillSource = fs.readFileSync(path.join(root, 'SKILL.md'), 'utf8')
167
+ const commandsSource = fs.readFileSync(path.join(root, 'references', 'commands.md'), 'utf8')
168
+ const promptLines = String(validData?.prompt ?? '').split(/\r?\n/).filter(Boolean)
169
+
170
+ const checks = [
171
+ check('CPF01', 'continue packet generator exists', fs.existsSync(path.join(root, 'scripts', 'generate-continue-packet.mjs')), 'scripts/generate-continue-packet.mjs'),
172
+ check('CPF02', '/gse continue routes through continue packet generator', runnerSource.includes("runNode('generate-continue-packet.mjs'") && runnerSource.includes("route: 'scripts/generate-continue-packet.mjs'"), 'scripts/run-gse-command.mjs'),
173
+ check('CPF03', 'valid fixture returns passed preflight and compact active-risk state', directValid.status === 0 && validData?.summary?.status === 'passed' && validData?.compactState?.riskCount === 4 && validData?.compactState?.activeRiskCount === 4 && validData?.compactState?.archivedRiskCount === 1 && validData?.compactState?.totalRiskCount === 5 && validData?.compactState?.topRisks?.length === 3, directValid.command),
174
+ check('CPF04', 'bad evidence index is a hard preflight failure', directInvalid.status !== 0 && invalidData?.summary?.status === 'failed' && invalidData?.preflight?.failures?.some((item) => item.id === 'CP03'), directInvalid.command),
175
+ check('CPF04b', 'bad evidence index returns concrete repair actions before implementation', directInvalid.status !== 0 && invalidData?.preflight?.failures?.some((item) => item.id === 'CP15') && invalidData?.compactState?.stateRepair?.repairActions?.some((item) => item.id === 'SR03'), directInvalid.command),
176
+ check('CPF05', 'portable /gse continue exposes structured preflight wrapper', commandValid.status === 0 && commandValidData?.execution?.command?.includes('generate-continue-packet.mjs') && commandValidData?.execution?.stdout?.includes('"compactState"'), commandValid.command),
177
+ check('CPF06', 'compact mode returns packet without wrapper diagnostics', commandCompact.status === 0 && commandCompactData?.compactState?.projectName === 'continue-fixture' && !commandCompact.stdout.includes('"execution"'), commandCompact.command),
178
+ check('CPF07', 'portable command fails when preflight has hard failures', commandInvalid.status !== 0 && commandInvalidData?.execution?.status !== 0 && commandInvalidData?.execution?.stdout?.includes('"status": "failed"'), commandInvalid.command),
179
+ check('CPF08', 'GSE self continue surfaces final acceptance status without treating optional host-native claims as blocked gates', gseSelf.status === 0 && ['passed', 'warning'].includes(gseSelfData?.summary?.status) && (gseSelfData?.compactState?.blockedGates?.length ?? 0) === 0 && gseSelfData?.ownerExternalGateSummary?.publicAccepted === 'verified', gseSelf.command),
180
+ check('CPF09', 'SKILL.md routes short continuation to hard preflight packet', skillSource.includes('generate-continue-packet.mjs') && skillSource.includes('Short continuation packet'), 'SKILL.md'),
181
+ check('CPF10', 'commands reference documents hard preflight semantics', commandsSource.includes('hard preflight') && commandsSource.includes('generate-continue-packet.mjs'), 'references/commands.md'),
182
+ check('CPF11b', 'continue packet surfaces historical evidence review queue', validData?.preflight?.checks?.some((item) => item.id === 'CP13') && validData?.compactState?.evidenceReviewQueue && typeof validData.compactState.evidenceReviewQueue.needsReview === 'number', 'compactState.evidenceReviewQueue'),
183
+ check('CPF11', 'continue packet surfaces state repair readiness', validData?.preflight?.checks?.some((item) => item.id === 'CP15') && validData?.compactState?.stateRepair?.status === 'clean', 'scripts/generate-continue-packet.mjs'),
184
+ check('CPF12', 'continue packet surfaces latest maintenance snapshot freshness', validData?.preflight?.checks?.some((item) => item.id === 'CP20') && validData?.compactState?.maintenanceSnapshot?.status === 'passed' && validData?.compactState?.maintenanceSnapshot?.installedSync === 'package-only', 'scripts/generate-continue-packet.mjs'),
185
+ check('CPF13', 'continue packet keeps owner/external records out of core workflow blockers', validData?.limits?.some((item) => item.includes('not GSE core workflow blockers')) && !validData?.limits?.some((item) => item.includes('block final acceptance')) && !fs.readFileSync(path.join(root, 'scripts', 'generate-continue-packet.mjs'), 'utf8').includes('Blocked final-acceptance gates'), 'scripts/generate-continue-packet.mjs'),
186
+ check('CPF14', 'continue packet exposes exact completion plan and close commands', Array.isArray(validData?.compactState?.completionPlan?.requiredCloseCommands) && validData.compactState.completionPlan.requiredCloseCommands.some((item) => item.includes('run-validation-profile.mjs')) && validData.compactState.completionPlan.requiredCloseCommands.some((item) => item.includes('/gse close')) && validData.compactState.completionPlan.requiredSteps.some((item) => item.includes('evidence/index.jsonl')), 'compactState.completionPlan'),
187
+ check('CPF15', 'continue packet activates conditional close commands from detected changed capability/docs/release files', validData?.compactState?.completionPlan?.conditionalCloseCommands?.some((item) => item.id === 'encoding' && item.active && item.command.includes('pnpm check:encoding')) && validData?.compactState?.completionPlan?.conditionalCloseCommands?.some((item) => item.id === 'installed-sync' && item.active && item.command.includes('audit-installed-sync.mjs')) && validData?.compactState?.completionPlan?.conditionalCloseCommands?.some((item) => item.id === 'release-bundle' && item.active && item.command.includes('generate-release-bundle.mjs')) && validData?.compactState?.completionPlan?.conditionalCloseCommands?.some((item) => item.id === 'session-sync' && item.active && item.command.includes('audit-session-sync.mjs')), 'compactState.completionPlan.conditionalCloseCommands'),
188
+ check('CPF16', 'continue packet exposes core/release/host-adapter gate taxonomy', validData?.compactState?.gateTaxonomy?.core?.blocking === true && validData?.compactState?.gateTaxonomy?.release?.scope?.includes('public release') && validData?.compactState?.gateTaxonomy?.hostAdapter?.scope?.includes('native slash-command') && validData?.compactState?.gateTaxonomy?.rule?.includes('block only the specific public, release, or host claim'), 'compactState.gateTaxonomy'),
189
+ check('CPF17', 'continue packet prompt is short-entry actionable instead of long-goal prose', promptLines.length <= 6 && validData?.prompt?.includes('GSE continue:') && validData?.prompt?.includes('Root:') && validData?.prompt?.includes('Slice:') && validData?.prompt?.includes('Next:') && validData?.prompt?.includes('Mode: continue-current-slice') && validData?.prompt?.includes('Do: one verifiable slice') && validData?.prompt?.includes('risks=4 active/1 archived') && !validData?.prompt?.includes('Run one verifiable slice, record evidence'), 'compact prompt line count and required action fields'),
190
+ check('CPF18', 'verified current slice switches short entry into open-next-slice mode', directVerified.status === 0 && verifiedData?.compactState?.nextSliceMode?.action === 'open-next-slice' && verifiedData?.compactState?.nextSliceMode?.currentSliceVerified === true && verifiedData?.prompt?.includes('Mode: open-next-slice'), directVerified.command),
191
+ check('CPF19', 'verified current slice exposes machine-readable next-slice candidates', directVerified.status === 0 && Array.isArray(verifiedData?.compactState?.nextSliceCandidates) && verifiedData.compactState.nextSliceCandidates.length >= 1 && verifiedData.compactState.nextSliceCandidates.every((item) => item.id && item.title && item.source && item.reason && item.fullReason && item.acceptanceHint && item.suggestedProfile), 'compactState.nextSliceCandidates'),
192
+ check('CPF20', 'unverified slice does not force next-slice candidates', directValid.status === 0 && validData?.compactState?.nextSliceMode?.action === 'continue-current-slice' && Array.isArray(validData?.compactState?.nextSliceCandidates) && validData.compactState.nextSliceCandidates.length === 0, 'compactState.nextSliceCandidates'),
193
+ check('CPF21', 'next-slice candidates do not claim native slash-command support', directVerified.status === 0 && !JSON.stringify(verifiedData?.compactState?.nextSliceCandidates ?? []).toLowerCase().includes('native slash-command'), 'compactState.nextSliceCandidates claim boundary'),
194
+ check('CPF22', 'next-slice candidates keep full machine reasons separate from short display reasons', directVerified.status === 0 && verifiedData?.compactState?.nextSliceCandidates?.every((item) => item.fullReason.length >= item.reason.length) && verifiedData?.compactState?.nextSliceCandidates?.some((item) => item.fullReason.length > item.reason.length), 'compactState.nextSliceCandidates.fullReason'),
195
+ check('CPF23', 'next-slice candidates prefer concrete gaps over meta open-next-slice reminders', directVerified.status === 0 && verifiedData?.compactState?.nextSliceCandidates?.[0]?.source === '.gse/state.json residualRisks' && !verifiedData.compactState.nextSliceCandidates[0].fullReason.toLowerCase().includes('open the next fixture slice'), 'compactState.nextSliceCandidates ranking'),
196
+ check('CPF24', 'next-slice candidates include structured action packets for short-entry takeover', directVerified.status === 0 && verifiedData?.compactState?.nextSliceCandidates?.every((item) => item.actionPacket?.candidateType && item.actionPacket?.outcomeHint && item.actionPacket?.scopeHint && item.actionPacket?.acceptanceHint && item.actionPacket?.evidenceHint && item.actionPacket?.riskHint && item.actionPacket?.nextActionHint && Array.isArray(item.actionPacket?.focusedChecks) && item.actionPacket.focusedChecks.length >= 1), 'compactState.nextSliceCandidates.actionPacket'),
197
+ check('CPF25', 'continue packet separates session sync evidence from target-session adoption', validData?.preflight?.checks?.some((item) => item.id === 'CP21') && validData?.compactState?.sessionSyncBoundary?.boundary === 'sync-records-do-not-prove-adoption' && validData?.compactState?.sessionSyncBoundary?.adoptionProven === false && validData?.compactState?.sessionSyncBoundary?.limits?.some((item) => item.includes('not target-session adoption')), 'compactState.sessionSyncBoundary'),
198
+ ]
199
+
200
+ fs.rmSync(validFixture, { recursive: true, force: true })
201
+ fs.rmSync(invalidFixture, { recursive: true, force: true })
202
+ fs.rmSync(verifiedFixture, { recursive: true, force: true })
203
+
204
+ const passed = checks.filter((item) => item.status === 'passed').length
205
+ const failed = checks.length - passed
206
+ const report = {
207
+ root,
208
+ generatedAt: new Date().toISOString(),
209
+ summary: { status: failed === 0 ? 'passed' : 'failed', passed, failed, total: checks.length },
210
+ workflows: {
211
+ continueHardPreflight: failed === 0 ? 'verified' : 'failed',
212
+ stateCompaction: failed === 0 ? 'verified' : 'failed',
213
+ ownerExternalGateBoundary: failed === 0 ? 'verified' : 'failed',
214
+ completionPlan: failed === 0 ? 'verified' : 'failed',
215
+ gateTaxonomy: failed === 0 ? 'verified' : 'failed',
216
+ shortEntryPrompt: failed === 0 ? 'verified' : 'failed',
217
+ nextSliceMode: failed === 0 ? 'verified' : 'failed',
218
+ nextSliceCandidates: failed === 0 ? 'verified' : 'failed',
219
+ nextSliceActionPackets: failed === 0 ? 'verified' : 'failed',
220
+ sessionSyncAdoptionBoundary: failed === 0 ? 'verified' : 'failed',
221
+ },
222
+ commands: [directValid.command, directInvalid.command, directVerified.command, commandValid.command, commandCompact.command, commandInvalid.command, gseSelf.command],
223
+ checks,
224
+ limits: [
225
+ 'This audit verifies portable /gse continue semantics and compact packet output.',
226
+ 'It does not prove native host slash-command execution.',
227
+ 'Owner/external records are surfaced as public/release/host-specific claim evidence, not GSE core workflow blockers.',
228
+ ],
229
+ }
230
+
231
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
232
+ else console.log(JSON.stringify(report, null, 2))
233
+
234
+ if (failed > 0) process.exit(1)