@t275005746/gse 0.1.1 → 0.2.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 (86) hide show
  1. package/.gse/releases/public-github-release-v0.1.2.md +49 -0
  2. package/.gse/releases/public-registry-publication-npm.md +49 -49
  3. package/.gse/state.json +148 -26
  4. package/CHANGELOG.md +52 -8
  5. package/README.md +13 -6
  6. package/README.zh-CN.md +13 -6
  7. package/SKILL.md +32 -12
  8. package/assets/templates/dispatch-packet.md +22 -14
  9. package/assets/templates/evidence.md +11 -5
  10. package/assets/templates/role-fallback-packet.md +49 -0
  11. package/package.json +18 -10
  12. package/references/agent-roles.md +41 -20
  13. package/references/commands.md +75 -45
  14. package/references/drift-audit.md +2 -1
  15. package/references/evidence-taxonomy.md +46 -9
  16. package/references/file-ownership.md +17 -13
  17. package/references/final-form-roadmap.md +203 -0
  18. package/references/final-readiness.md +3 -3
  19. package/references/host-adapters.md +38 -10
  20. package/references/learning-system.md +24 -8
  21. package/references/maintenance-cadence.md +51 -0
  22. package/references/project-guards.md +52 -0
  23. package/references/quality-gates.md +18 -11
  24. package/references/role-dispatch-fallback.md +54 -0
  25. package/references/tool-adapters.md +13 -3
  26. package/scripts/audit-close-gate-hardening.mjs +188 -0
  27. package/scripts/audit-close-gate.mjs +219 -33
  28. package/scripts/audit-command-execution.mjs +30 -17
  29. package/scripts/audit-commands.mjs +7 -5
  30. package/scripts/audit-completion-plan-drill.mjs +271 -0
  31. package/scripts/audit-completion-readiness.mjs +9 -6
  32. package/scripts/audit-continue-preflight.mjs +318 -0
  33. package/scripts/audit-evidence-levels.mjs +217 -0
  34. package/scripts/audit-evidence-review-queue.mjs +206 -0
  35. package/scripts/audit-final-acceptance-packet.mjs +9 -9
  36. package/scripts/audit-final-form-progress-report.mjs +19 -18
  37. package/scripts/audit-final-form-roadmap.mjs +157 -0
  38. package/scripts/audit-final-form-stale-copy.mjs +2 -2
  39. package/scripts/audit-final-readiness.mjs +3 -3
  40. package/scripts/audit-fresh-session-readiness.mjs +1 -1
  41. package/scripts/audit-host-capabilities.mjs +237 -0
  42. package/scripts/audit-installed-sync.mjs +203 -0
  43. package/scripts/audit-learning-drift.mjs +292 -0
  44. package/scripts/audit-learning-promotion.mjs +351 -0
  45. package/scripts/audit-learning-system.mjs +24 -14
  46. package/scripts/audit-local-final-form-completion.mjs +11 -10
  47. package/scripts/audit-maintenance-cadence.mjs +139 -0
  48. package/scripts/audit-maintenance-snapshot.mjs +181 -0
  49. package/scripts/audit-npm-package-metadata.mjs +8 -2
  50. package/scripts/audit-npm-publish-dry-run.mjs +10 -4
  51. package/scripts/audit-npm-tarball-install.mjs +9 -3
  52. package/scripts/audit-owner-external-gate-kit.mjs +12 -11
  53. package/scripts/audit-project-guards.mjs +189 -0
  54. package/scripts/audit-project.mjs +14 -11
  55. package/scripts/audit-public-acceptance-handoff.mjs +10 -10
  56. package/scripts/audit-public-acceptance-readiness.mjs +6 -6
  57. package/scripts/audit-public-release-checklist.mjs +17 -15
  58. package/scripts/audit-release-bundle.mjs +13 -11
  59. package/scripts/audit-release-owner-action-plan-drill.mjs +5 -4
  60. package/scripts/audit-release-owner-action-plan.mjs +10 -10
  61. package/scripts/audit-release-status-manifest.mjs +4 -4
  62. package/scripts/audit-roadmap-consistency.mjs +11 -7
  63. package/scripts/audit-role-dispatch-fallback.mjs +212 -0
  64. package/scripts/audit-session-sync.mjs +127 -0
  65. package/scripts/audit-state-freshness.mjs +6 -5
  66. package/scripts/audit-state-repair.mjs +360 -0
  67. package/scripts/audit-target-hardening-drills.mjs +518 -0
  68. package/scripts/audit-tool-fallback-policy.mjs +180 -0
  69. package/scripts/audit-ui-browser-evidence-policy.mjs +191 -0
  70. package/scripts/audit-validation-profiles.mjs +6 -4
  71. package/scripts/backfill-evidence-levels.mjs +98 -0
  72. package/scripts/check-encoding.mjs +72 -0
  73. package/scripts/generate-continue-packet.mjs +1487 -0
  74. package/scripts/generate-final-acceptance-packet.mjs +23 -8
  75. package/scripts/generate-final-form-progress-report.mjs +25 -23
  76. package/scripts/generate-host-runtime-evidence-handoff.mjs +23 -16
  77. package/scripts/generate-maintenance-snapshot.mjs +216 -0
  78. package/scripts/generate-public-acceptance-handoff.mjs +26 -14
  79. package/scripts/generate-release-owner-action-plan.mjs +4 -3
  80. package/scripts/generate-release-status-manifest.mjs +4 -3
  81. package/scripts/init-project.mjs +144 -63
  82. package/scripts/record-learning.mjs +37 -8
  83. package/scripts/record-session-sync.mjs +87 -0
  84. package/scripts/run-gse-command.mjs +79 -47
  85. package/scripts/run-validation-profile.mjs +24 -5
  86. package/scripts/validate-gse.mjs +262 -9
@@ -200,24 +200,39 @@ const results = [
200
200
  subagents: 'unknown',
201
201
  ci: 'unknown',
202
202
  },
203
- lastEvidence: '.gse/evidence/index.jsonl',
203
+ lastEvidence: `.gse/evidence/${date}.md`,
204
204
  residualRisks: [
205
205
  'Project commands and host tools are unknown until verified in this repository.',
206
206
  ],
207
207
  }),
208
208
  ),
209
- writeIfMissing(
210
- 'evidence/index.jsonl',
209
+ writeIfMissing(
210
+ 'evidence/index.jsonl',
211
211
  JSON.stringify({
212
- date,
213
- recordType: 'adoption',
214
- status: 'result',
215
- summary: `Initialized GSE ${mode} scaffold.`,
216
- evidenceFile: `.gse/evidence/${date}.md`,
212
+ date,
213
+ recordType: 'adoption',
214
+ status: 'result',
215
+ evidenceLevel: 'result',
216
+ requiredEvidenceLevel: 'verified-unit',
217
+ summary: `Initialized GSE ${mode} scaffold.`,
218
+ evidenceFile: `.gse/evidence/${date}.md`,
217
219
  commands: [`node <gse-skill>/scripts/init-project.mjs --target <project-root> --mode ${requestedMode}`],
218
- nextAction: 'Record project-specific profile, canonical plan, quality gates, and first verified slice.',
219
- }) + '\n',
220
- ),
220
+ nextAction: 'Record project-specific profile, canonical plan, quality gates, and first verified slice.',
221
+ }) + '\n',
222
+ ),
223
+ writeIfMissing(
224
+ `evidence/${date}.md`,
225
+ `# GSE Adoption Evidence
226
+
227
+ - Date: ${date}
228
+ - Status: result
229
+ - Evidence level: result
230
+ - Summary: Initialized GSE ${mode} scaffold.
231
+ - Command: \`node <gse-skill>/scripts/init-project.mjs --target <project-root> --mode ${requestedMode}\`
232
+
233
+ Next action: Record project-specific profile, canonical plan, quality gates, and first verified slice.
234
+ `,
235
+ ),
221
236
  writeIfMissing(
222
237
  'README.md',
223
238
  `# GSE Workflow
@@ -230,8 +245,9 @@ Start meaningful work by reading:
230
245
  2. .gse/state.json.
231
246
  3. .gse/project-profile.md.
232
247
  4. .gse/goal-map.md.
233
- 5. .gse/quality-gates.md.
234
- 6. The relevant change folder under .gse/changes/ when one exists.
248
+ 5. .gse/quality-gates.md.
249
+ 6. .gse/project-guards.md.
250
+ 7. The relevant change folder under .gse/changes/ when one exists.
235
251
 
236
252
  Core loop:
237
253
 
@@ -336,8 +352,8 @@ Describe the durable project outcome here.
336
352
  - Add project-specific risks here.
337
353
  `,
338
354
  ),
339
- writeIfMissing(
340
- 'quality-gates.md',
355
+ writeIfMissing(
356
+ 'quality-gates.md',
341
357
  `# Quality Gates
342
358
 
343
359
  ## Universal
@@ -361,12 +377,31 @@ Describe the durable project outcome here.
361
377
 
362
378
  ## Learning
363
379
 
364
- - Capture reusable lessons and promote recurring issues into gates.
365
- `,
366
- ),
367
- writeIfMissing(
368
- 'tooling.md',
369
- `# Tooling
380
+ - Capture reusable lessons and promote recurring issues into gates.
381
+ `,
382
+ ),
383
+ writeIfMissing(
384
+ 'project-guards.md',
385
+ `# Project Guards
386
+
387
+ Project guards are reusable preflight rules promoted from repeated project lessons.
388
+
389
+ GSE reads this file during \`/gse continue\` and surfaces active guards before implementation. Keep it short, project-local, and evidence-bound.
390
+
391
+ | ID | Guard | Severity | Trigger | Check | Status |
392
+ |---|---|---|---|---|---|
393
+ | WIN-SHELL | Use shell syntax that matches the active host. On Windows, prefer \`cmd /c\` for npm, pnpm, npx, and similar commands when PowerShell shims or operators are unreliable. | high | Windows shell or package-manager command | Confirm command syntax is valid for the current shell before running or documenting it. | active |
394
+ | SPARSE-GIT | Check sparse checkout before staging generated workflow folders. | high | \`.gse/\`, host adapter, or generated scaffold changes | If sparse checkout is active and the path is outside the cone, use sparse-aware staging or record the limitation. | active |
395
+ | UTF8-DOC | Use UTF-8-safe readers for Chinese or multilingual docs before judging mojibake. | high | Chinese docs, encoding complaints, generated docs | Read with Node UTF-8 or another UTF-8-safe viewer; run the project encoding check when docs changed. | active |
396
+ | EVIDENCE-STALE | Treat stale, broken, or schema-weak evidence as a preflight problem. | high | \`.gse/evidence/index.jsonl\`, state, close gate | Validate JSONL and make sure latest evidence matches the current slice before closing. | active |
397
+ | UI-EVIDENCE | Label UI/browser verification downgrades explicitly. | medium | UI, browser, screenshot, component test, visual behavior | Mark evidence as unit, component, API, browser, CI, owner, release, or external instead of hiding downgrade under a generic verified label. | active |
398
+ | SUBAGENT-HONEST | Do not claim subagent dispatch unless the current host exposes real dispatch evidence. | high | multi-agent, subagent, role dispatch, parallel work | If no real dispatch tool exists, run roles sequentially or use file/tool parallelism and say so. | active |
399
+ | SYNC-NO-INTERRUPT | Do not interrupt running project sessions with cross-thread GSE sync messages. | high | GSE upgrade sync, delegation, background thread message | Prefer evidence records or owner action notes; only send a short cross-thread sync when the target session is idle or the owner explicitly asks. | active |
400
+ `,
401
+ ),
402
+ writeIfMissing(
403
+ 'tooling.md',
404
+ `# Tooling
370
405
 
371
406
  Minimum tools: git, shell, and project test/build commands.
372
407
 
@@ -379,12 +414,30 @@ Recommended tools:
379
414
  - Comet for change lifecycle when available.
380
415
  - Self-improvement or learnings files for durable lessons.
381
416
 
382
- Do not claim a tool was used when it was not available.
383
- `,
384
- ),
385
- writeIfMissing(
386
- 'learnings.md',
387
- `# Learnings
417
+ Do not claim a tool was used when it was not available.
418
+ `,
419
+ ),
420
+ writeIfMissing(
421
+ 'host-capabilities.md',
422
+ `# Host Capabilities
423
+
424
+ Record current project and host capability facts here. A generated adapter, portable command, or another host's evidence is not proof for this host.
425
+
426
+ Status vocabulary: \`verified\`, \`documented\`, \`unknown\`, \`unavailable\`, \`external-required\`.
427
+
428
+ | Capability | Host/Tool | Status | Evidence | Claim Boundary | Last Checked |
429
+ |---|---|---|---|---|---|
430
+ | native-slash-command | current host | external-required | - | Native slash-command support requires real host runtime invocation evidence, not portable \`/gse\` runner output. | - |
431
+ | browser | browser or Playwright | unknown | - | Browser proof requires a real browser/component/screenshot command for this project. | - |
432
+ | mcp | MCP servers | unknown | - | MCP status is host and project specific. | - |
433
+ | lsp | LSP or code index | unknown | - | LSP/index status is current-session specific unless project docs prove it. | - |
434
+ | subagent | host dispatch | unknown | - | Real subagent dispatch requires verified host/tool evidence; sequential role fallback is not real dispatch. | - |
435
+ | ci | project CI | unknown | - | CI is verified only after a workflow/config or run is checked for this project. | - |
436
+ `,
437
+ ),
438
+ writeIfMissing(
439
+ 'learnings.md',
440
+ `# Learnings
388
441
 
389
442
  Record only reusable lessons.
390
443
 
@@ -417,13 +470,19 @@ Record only reusable lessons.
417
470
  ## Next Action
418
471
  `,
419
472
  ),
420
- writeIfMissing(
421
- 'templates/evidence.md',
422
- `# Evidence
423
-
424
- ## Commands
425
-
426
- ## Results
473
+ writeIfMissing(
474
+ 'templates/evidence.md',
475
+ `# Evidence
476
+
477
+ ## Status
478
+
479
+ - Evidence status:
480
+ - Evidence level:
481
+ - Required evidence level:
482
+
483
+ ## Commands
484
+
485
+ ## Results
427
486
 
428
487
  ## Files Changed
429
488
 
@@ -582,10 +641,11 @@ Host-specific folders such as .codex/, .claude/, .agents/, or runtime-specific d
582
641
 
583
642
  - Goal map: .gse/goal-map.md
584
643
  - Quality gates: .gse/quality-gates.md
585
- - Agent roles: .gse/agents/roles.md
586
- - Dispatch rules: .gse/agents/dispatch.md
587
- - Project skills: .gse/skills/README.md
588
- - LSP/index notes: .gse/lsp/README.md
644
+ - Agent roles: .gse/agents/roles.md
645
+ - Dispatch rules: .gse/agents/dispatch.md
646
+ - Role fallback packets: .gse/agents/role-fallback-packets.md
647
+ - Project skills: .gse/skills/README.md
648
+ - LSP/index notes: .gse/lsp/README.md
589
649
 
590
650
  ## Adapter Rule
591
651
 
@@ -598,43 +658,64 @@ Do not duplicate the whole workflow into a host-specific folder. Add a short poi
598
658
 
599
659
  Use these roles as boundaries, whether they are executed by real subagents or sequentially by one agent.
600
660
 
601
- | Role | Responsibility | Write Access |
602
- |---|---|---|
603
- | Coordinator | Scope, context, final judgment, integration | yes |
604
- | Product Analyst | Outcome, user pain, priority, non-goals | docs only |
605
- | Architect | Contracts, data flow, risks, rollback | docs/code by assignment |
606
- | Code Locator | Files, symbols, call chains, existing tests | no |
607
- | Builder | Bounded implementation slice | assigned files only |
608
- | Reviewer | Diff review, regressions, missing tests | no |
609
- | QA | Focused verification and evidence | test/evidence only |
610
- | Docs/Evidence | Slice log, ADR links, learning entries | docs only |
611
- `,
612
- ),
661
+ | Role | Responsibility | Write Access |
662
+ |---|---|---|
663
+ | Coordinator | Scope, context, final judgment, integration | yes |
664
+ | Planner | Outcome, scope, acceptance, evidence, risk, next action | docs/state only |
665
+ | Product Analyst | Outcome, user pain, priority, non-goals | docs only |
666
+ | Architect | Contracts, data flow, risks, rollback | docs/code by assignment |
667
+ | Locator | Files, symbols, call chains, existing tests | no |
668
+ | Implementer | Bounded implementation slice | assigned files only |
669
+ | Verifier | Focused checks and evidence level | evidence/test output only |
670
+ | Reviewer | Diff review, regressions, missing tests | no |
671
+ | Docs/Evidence | Slice log, ADR links, learning entries | docs only |
672
+ | Release | Release, owner, CI, package, marketplace, registry, and host-runtime boundaries | docs/release only |
673
+ `,
674
+ ),
613
675
  writeIfMissing(
614
676
  'agents/dispatch.md',
615
677
  `# Agent Dispatch
616
678
 
617
679
  Use real subagent tools only when the host exposes them.
618
680
 
619
- ## Dispatch Packet
620
-
621
- - Role:
622
- - Objective:
623
- - Allowed files:
624
- - Forbidden actions:
625
- - Expected output:
626
- - Verification:
681
+ ## Dispatch Packet
682
+
683
+ - Role:
684
+ - Real delegation used: yes | no
685
+ - Objective:
686
+ - Allowed files:
687
+ - Forbidden actions:
688
+ - Role output evidence:
689
+ - Expected output:
690
+ - Verification:
627
691
 
628
692
  ## Rules
629
693
 
630
694
  - Do not delegate final judgment.
631
695
  - Avoid parallel writes to the same file.
632
696
  - Say explicitly when subagent tools are unavailable and execute roles sequentially.
633
- - Keep prompts free of expected answers when using agents for validation.
634
- `,
635
- ),
636
- writeIfMissing(
637
- 'skills/README.md',
697
+ - Keep prompts free of expected answers when using agents for validation.
698
+ `,
699
+ ),
700
+ writeIfMissing(
701
+ 'agents/role-fallback-packets.md',
702
+ `# Role Fallback Packets
703
+
704
+ These packets make role-separated work auditable even when real subagent tools are unavailable.
705
+
706
+ | Role | Mode | Real delegation used | Tool status | Fallback output | Evidence | Stop condition | Write access |
707
+ |---|---|---|---|---|---|---|---|
708
+ | Planner | sequential-role | no | unknown | Slice plan with outcome, scope, acceptance, evidence, risk, and next action | .gse/current-slice.md or planning note | Goal, roadmap, or acceptance source is contradictory | docs/state only |
709
+ | Locator | sequential-role | no | unknown | File, symbol, command, and existing-test map | search output or locator notes | Required files cannot be found or ownership is unclear | read-only |
710
+ | Implementer | sequential-role | no | unknown | Bounded diff in assigned files | git diff and changed-file list | Target files have unsafe unrelated dirty changes | assigned files only |
711
+ | Verifier | sequential-role | no | unknown | Focused command results and evidence level | command output summary and evidence record | Required focused check cannot run or fails without a repair path | evidence/test output only |
712
+ | Reviewer | sequential-role | no | unknown | Spec compliance and quality findings | review notes or explicit no-findings statement | Diff exceeds scope or missing tests are material | read-only |
713
+ | Docs/Evidence | sequential-role | no | unknown | Slice evidence, state, goal-map, and roadmap updates | .gse/evidence/index.jsonl and .gse/evidence/YYYY-MM-DD.md | Evidence cannot be recorded or JSONL is invalid | docs/evidence only |
714
+ | Release | sequential-role | no | unknown | Release, owner, external, CI, package, and host-runtime boundary check | final-readiness or public-acceptance audit summary | Local evidence is being used to claim owner/external support | docs/release only |
715
+ `,
716
+ ),
717
+ writeIfMissing(
718
+ 'skills/README.md',
638
719
  `# Project Skills
639
720
 
640
721
  Record project-local skills and reusable workflows here.
@@ -72,10 +72,10 @@ if (!fs.existsSync(gseDir) || !fs.statSync(gseDir).isDirectory()) {
72
72
  process.exit(1)
73
73
  }
74
74
 
75
- const existing = fs.existsSync(learningsPath) ? fs.readFileSync(learningsPath, 'utf8').replace(/^\uFEFF/, '') : '# Learnings\n\n'
76
- const duplicate = existing
77
- .split(/\r?\n/)
78
- .some((line) => line.trim().startsWith('- Summary:') && normalize(line.replace(/^- Summary:\s*/, '')) === normalize(summary))
75
+ const existing = fs.existsSync(learningsPath) ? fs.readFileSync(learningsPath, 'utf8').replace(/^\uFEFF/, '') : '# Learnings\n\n'
76
+ const existingLines = existing.split(/\r?\n/)
77
+ const duplicateSummaryLineIndex = existingLines.findIndex((line) => line.trim().startsWith('- Summary:') && normalize(line.replace(/^- Summary:\s*/, '')) === normalize(summary))
78
+ const duplicate = duplicateSummaryLineIndex !== -1
79
79
 
80
80
  const relativePath = path.relative(target, learningsPath).replace(/\\/g, '/')
81
81
  const entry = [
@@ -90,10 +90,39 @@ const entry = [
90
90
  '',
91
91
  ].join('\n')
92
92
 
93
- if (duplicate) {
94
- report({
95
- status: 'skipped',
96
- target,
93
+ if (duplicate) {
94
+ if (execute) {
95
+ let insertAt = duplicateSummaryLineIndex + 1
96
+ let occurrenceLineIndex = -1
97
+ for (let cursor = duplicateSummaryLineIndex + 1; cursor < existingLines.length; cursor += 1) {
98
+ const line = existingLines[cursor]
99
+ if (/^##\s+/.test(line)) break
100
+ if (line.trim().startsWith('- Occurrences:')) {
101
+ occurrenceLineIndex = cursor
102
+ break
103
+ }
104
+ if (line.trim().startsWith('- Source:')) insertAt = cursor
105
+ }
106
+ if (occurrenceLineIndex === -1) {
107
+ existingLines.splice(insertAt, 0, '- Occurrences: 2')
108
+ } else {
109
+ const current = Number(existingLines[occurrenceLineIndex].replace(/^- Occurrences:\s*/, '').trim()) || 1
110
+ existingLines[occurrenceLineIndex] = '- Occurrences: ' + String(current + 1)
111
+ }
112
+ fs.writeFileSync(learningsPath, existingLines.join('\n').replace(/\n*$/, '\n'), 'utf8')
113
+ report({
114
+ status: 'updated',
115
+ target,
116
+ path: relativePath,
117
+ summary,
118
+ reason: 'duplicate summary counted without appending another entry',
119
+ evidenceStatus: 'verified',
120
+ })
121
+ process.exit(0)
122
+ }
123
+ report({
124
+ status: 'skipped',
125
+ target,
97
126
  path: relativePath,
98
127
  summary,
99
128
  reason: 'duplicate summary already exists',
@@ -0,0 +1,87 @@
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 execute = args.includes('--execute')
15
+ const jsonOnly = args.includes('--json')
16
+ const recordPath = path.join(root, '.gse', 'session-sync.jsonl')
17
+
18
+ function requiredArg(name) {
19
+ const value = readArg(name)
20
+ if (!value) {
21
+ console.error(`${name} is required`)
22
+ process.exit(1)
23
+ }
24
+ return value
25
+ }
26
+
27
+ function normalizeStatus(value) {
28
+ return String(value || '').trim().toLowerCase()
29
+ }
30
+
31
+ const allowedStatuses = new Set([
32
+ 'sent',
33
+ 'installed-sync',
34
+ 'skipped',
35
+ 'failed',
36
+ 'archived',
37
+ 'unavailable',
38
+ ])
39
+
40
+ const status = normalizeStatus(requiredArg('--status'))
41
+ if (!allowedStatuses.has(status)) {
42
+ console.error(`--status must be one of: ${[...allowedStatuses].join(', ')}`)
43
+ process.exit(1)
44
+ }
45
+
46
+ const record = {
47
+ schemaVersion: 1,
48
+ recordedAt: new Date().toISOString(),
49
+ capability: readArg('--capability', 'gse-capability-sync'),
50
+ status,
51
+ method: requiredArg('--method'),
52
+ threadId: readArg('--thread-id', null),
53
+ project: readArg('--project', null),
54
+ workspace: readArg('--workspace', null),
55
+ evidence: requiredArg('--evidence'),
56
+ messageSummary: readArg('--message-summary', ''),
57
+ limits: [
58
+ 'This record proves a sync attempt or installed-copy parity record, not that the target session adopted the capability.',
59
+ 'A thread sync is accepted only when the transport returned success or when the failure/archived status is recorded honestly.',
60
+ ],
61
+ }
62
+
63
+ const report = {
64
+ root,
65
+ recordPath,
66
+ execute,
67
+ summary: {
68
+ status: execute ? 'written' : 'dry-run',
69
+ threadId: record.threadId,
70
+ syncStatus: record.status,
71
+ method: record.method,
72
+ },
73
+ record,
74
+ }
75
+
76
+ if (execute) {
77
+ fs.mkdirSync(path.dirname(recordPath), { recursive: true })
78
+ fs.appendFileSync(recordPath, JSON.stringify(record) + '\n', 'utf8')
79
+ }
80
+
81
+ if (jsonOnly) console.log(JSON.stringify(report, null, 2))
82
+ else {
83
+ console.log(`GSE session sync record: ${report.summary.status}`)
84
+ console.log(`Status: ${record.status}`)
85
+ console.log(`Method: ${record.method}`)
86
+ if (record.threadId) console.log(`Thread: ${record.threadId}`)
87
+ }
@@ -95,26 +95,31 @@ const commandMap = {
95
95
  effect: 'read-only',
96
96
  summary: 'Show GSE commands and project entry files.',
97
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.',
98
+ continue: {
99
+ route: 'scripts/generate-continue-packet.mjs',
100
+ effect: 'read-only',
101
+ summary: 'Run a hard continuation preflight and generate a compact state packet.',
102
+ },
103
+ next: {
104
+ route: 'scripts/generate-continue-packet.mjs',
105
+ effect: 'read-only',
106
+ summary: 'Alias for /gse continue.',
107
107
  },
108
108
  status: {
109
109
  route: 'scripts/generate-final-form-progress-report.mjs or .gse/state.json',
110
110
  effect: 'read-only',
111
111
  summary: 'Show project state, or GSE final-form progress when the target is the GSE skill.',
112
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
- },
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 claim evidence for GSE, or target-project GSE readiness for normal projects.',
117
+ },
118
+ repair: {
119
+ route: 'scripts/audit-state-repair.mjs',
120
+ effect: 'read-only by default; reversible risk compaction with --execute',
121
+ summary: 'Diagnose or safely repair stale state, broken evidence JSONL, and overlong residual risks.',
122
+ },
118
123
  acceptance: {
119
124
  route: 'scripts/audit-public-acceptance-readiness.mjs or scripts/audit-target-project.mjs',
120
125
  effect: 'read-only',
@@ -145,11 +150,16 @@ const commandMap = {
145
150
  effect: 'read-only by default; write-with-execute for install target writes',
146
151
  summary: 'Dry-run or install GSE from a local package path or URL-shaped package source.',
147
152
  },
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
+ 'public-release': {
154
+ route: 'scripts/generate-public-release-checklist.mjs or scripts/audit-public-release-checklist.mjs',
155
+ effect: 'read-only by default; write-with-execute for canonical checklist generation',
156
+ summary: 'Dry-run or generate the ordered owner/public release checklist.',
157
+ },
158
+ maintenance: {
159
+ route: 'scripts/generate-maintenance-snapshot.mjs',
160
+ effect: 'read-only',
161
+ summary: 'Generate a recurring maintenance snapshot for benchmark, drift, evidence, installed sync, session sync, and release freshness checks.',
162
+ },
153
163
  owner: {
154
164
  route: 'scripts/audit-public-acceptance-readiness.mjs',
155
165
  effect: 'read-only',
@@ -170,11 +180,11 @@ const commandMap = {
170
180
  effect: 'read-only',
171
181
  summary: 'Select and run focused verification according to project quality gates.',
172
182
  },
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
- },
183
+ learn: {
184
+ route: 'scripts/record-learning.mjs or scripts/audit-learning-promotion.mjs',
185
+ effect: 'read-only by default; write-with-execute for .gse/learnings.md or candidate-only .gse/learning-promotions.md',
186
+ summary: 'Record a reusable project lesson, or run promotion analysis with --promote.',
187
+ },
178
188
  slice: {
179
189
  route: 'references/spec-workflow.md',
180
190
  effect: 'read-only',
@@ -207,8 +217,8 @@ if (execute && verb === 'init') {
207
217
  const changeId = rest.find((item) => !item.startsWith('--')) ?? 'gse-change'
208
218
  const level = rest.includes('--level') ? rest[rest.indexOf('--level') + 1] : 'standard'
209
219
  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'])
220
+ } else if (verb === 'continue' || verb === 'next') {
221
+ execution = runNode('generate-continue-packet.mjs', ['--root', root, '--target', target, '--json'])
212
222
  } else if (verb === 'status') {
213
223
  const targetHasFinalFormReport = fs.existsSync(path.join(target, 'scripts', 'generate-final-form-progress-report.mjs'))
214
224
  && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
@@ -238,13 +248,19 @@ if (execute && verb === 'init') {
238
248
  }),
239
249
  stderr: state ? '' : '.gse/state.json is missing or invalid',
240
250
  }
241
- } else if (verb === 'doctor' || verb === 'acceptance') {
251
+ } else if (verb === 'doctor' || verb === 'acceptance') {
242
252
  const targetHasPublicAcceptanceDoctor = fs.existsSync(path.join(target, 'scripts', 'audit-public-acceptance-readiness.mjs'))
243
253
  && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
244
254
  execution = targetHasPublicAcceptanceDoctor
245
255
  ? 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') {
256
+ : runNode('audit-target-project.mjs', ['--target', target, '--json'])
257
+ } else if (verb === 'repair') {
258
+ const repairArgs = ['--root', root, '--target', target, '--json']
259
+ if (execute) repairArgs.push('--write')
260
+ const maxRiskIndex = rest.indexOf('--max-active-risks')
261
+ if (maxRiskIndex !== -1) repairArgs.push('--max-active-risks', rest[maxRiskIndex + 1] || '6')
262
+ execution = runNode('audit-state-repair.mjs', repairArgs)
263
+ } else if (verb === 'owner-actions' || verb === 'owner') {
248
264
  const targetHasPublicAcceptanceDoctor = fs.existsSync(path.join(target, 'scripts', 'audit-public-acceptance-readiness.mjs'))
249
265
  && fs.existsSync(path.join(target, 'references', 'final-readiness.md'))
250
266
  if (targetHasPublicAcceptanceDoctor) {
@@ -445,7 +461,7 @@ if (execute && verb === 'init') {
445
461
  stderr: 'target does not expose scripts/install-gse.mjs',
446
462
  }
447
463
  }
448
- } else if (verb === 'public-release') {
464
+ } else if (verb === 'public-release') {
449
465
  const targetHasPublicReleaseChecklist = fs.existsSync(path.join(target, 'scripts', 'generate-public-release-checklist.mjs'))
450
466
  && fs.existsSync(path.join(target, 'scripts', 'audit-public-release-checklist.mjs'))
451
467
  if (targetHasPublicReleaseChecklist) {
@@ -471,9 +487,19 @@ if (execute && verb === 'init') {
471
487
  error: '/gse public-release is only available for GSE skill packages that include public release checklist scripts.',
472
488
  }),
473
489
  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') {
490
+ }
491
+ }
492
+ } else if (verb === 'maintenance') {
493
+ const maintenanceArgs = ['--root', target, '--target', target, '--json']
494
+ const installedRootIndex = rest.indexOf('--installed-root')
495
+ if (installedRootIndex !== -1 && rest[installedRootIndex + 1]) maintenanceArgs.push('--installed-root', rest[installedRootIndex + 1])
496
+ const outIndex = rest.indexOf('--out')
497
+ if (outIndex !== -1 && rest[outIndex + 1]) maintenanceArgs.push('--out', path.resolve(rest[outIndex + 1]))
498
+ if (rest.includes('--skip-release-bundle')) maintenanceArgs.push('--skip-release-bundle')
499
+ if (rest.includes('--package-smoke')) maintenanceArgs.push('--package-smoke')
500
+ if (execute) maintenanceArgs.push('--execute')
501
+ execution = runNode('generate-maintenance-snapshot.mjs', maintenanceArgs)
502
+ } else if (verb === 'audit') {
477
503
  execution = runNode('audit-target-project.mjs', ['--target', target, '--json'])
478
504
  } else if (verb === 'close') {
479
505
  execution = runNode('audit-close-gate.mjs', ['--target', target, '--json'])
@@ -481,20 +507,26 @@ if (execute && verb === 'init') {
481
507
  const profileIndex = rest.indexOf('--profile')
482
508
  const profile = profileIndex === -1 ? 'lite' : (rest[profileIndex + 1] || 'lite')
483
509
  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
- }
510
+ } else if (verb === 'learn') {
511
+ if (rest.includes('--promote')) {
512
+ const promotionArgs = ['--root', root, '--target', target, '--json']
513
+ if (execute) promotionArgs.push('--write')
514
+ execution = runNode('audit-learning-promotion.mjs', promotionArgs)
515
+ } else {
516
+ const learningArgs = [
517
+ '--target', target,
518
+ '--summary', readRestValue(rest, '--summary'),
519
+ '--trigger', readRestValue(rest, '--trigger', 'reusable lesson'),
520
+ '--source', readRestValue(rest, '--source', 'run-gse-command'),
521
+ '--promotion', readRestValue(rest, '--promotion', 'first occurrence: learning note'),
522
+ '--json',
523
+ ]
524
+ const impact = readRestValue(rest, '--impact')
525
+ if (impact) learningArgs.push('--impact', impact)
526
+ if (execute) learningArgs.push('--execute')
527
+ execution = runNode('record-learning.mjs', learningArgs)
528
+ }
529
+ }
498
530
 
499
531
  const report = {
500
532
  root,
@@ -48,11 +48,30 @@ function run(script, commandArgs) {
48
48
  }
49
49
 
50
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
- ]
51
+ const common = [
52
+ ['audit-commands.mjs', ['--root', root, '--json']],
53
+ ['audit-continue-preflight.mjs', ['--root', root, '--json']],
54
+ ['audit-completion-plan-drill.mjs', ['--root', root, '--json']],
55
+ ['audit-project-guards.mjs', ['--root', root, '--json']],
56
+ ['backfill-evidence-levels.mjs', ['--root', target, '--json']],
57
+ ['audit-evidence-levels.mjs', ['--root', root, '--target', target, '--json']],
58
+ ['audit-evidence-review-queue.mjs', ['--root', root, '--target', target, '--json']],
59
+ ['audit-ui-browser-evidence-policy.mjs', ['--root', root, '--target', target, '--json']],
60
+ ['audit-role-dispatch-fallback.mjs', ['--root', root, '--target', target, '--json']],
61
+ ['audit-close-gate-hardening.mjs', ['--root', root, '--json']],
62
+ ['audit-state-repair.mjs', ['--root', root, '--target', target, '--json']],
63
+ ['audit-learning-promotion.mjs', ['--root', root, '--target', target, '--json']],
64
+ ['audit-learning-drift.mjs', ['--root', root, '--target', target, '--json']],
65
+ ['audit-host-capabilities.mjs', ['--root', root, '--target', target, '--json']],
66
+ ['audit-tool-fallback-policy.mjs', ['--root', root, '--target', target, '--json']],
67
+ ['audit-target-hardening-drills.mjs', ['--root', root, '--json']],
68
+ ['audit-maintenance-cadence.mjs', ['--root', root, '--json']],
69
+ ['audit-maintenance-snapshot.mjs', ['--root', root, '--json']],
70
+ ['audit-installed-sync.mjs', ['--root', root, '--json']],
71
+ ['audit-session-sync.mjs', ['--root', root, '--json']],
72
+ ['audit-command-execution.mjs', ['--root', root, '--profile', 'lite', '--json']],
73
+ ['audit-learning-system.mjs', ['--root', root, '--json']],
74
+ ]
56
75
 
57
76
  const targetChecks = target === root
58
77
  ? []