@ryuenn3123/agentic-senior-core 2.0.5 → 2.0.8

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 (126) hide show
  1. package/.agent-context/blueprints/mobile-app.md +91 -21
  2. package/.agent-context/profiles/platform.md +13 -13
  3. package/.agent-context/profiles/regulated.md +13 -13
  4. package/.agent-context/profiles/startup.md +13 -13
  5. package/.agent-context/prompts/review-code.md +3 -3
  6. package/.agent-context/review-checklists/frontend-skill-parity.md +28 -28
  7. package/.agent-context/review-checklists/frontend-usability.md +33 -33
  8. package/.agent-context/review-checklists/pr-checklist.md +11 -6
  9. package/.agent-context/review-checklists/release-operations.md +29 -29
  10. package/.agent-context/rules/api-docs.md +34 -0
  11. package/.agent-context/skills/README.md +62 -62
  12. package/.agent-context/skills/backend/README.md +67 -67
  13. package/.agent-context/skills/backend/architecture.md +360 -360
  14. package/.agent-context/skills/backend/compatibility-manifest.json +8 -8
  15. package/.agent-context/skills/backend/data-access.md +230 -230
  16. package/.agent-context/skills/backend/errors.md +137 -137
  17. package/.agent-context/skills/backend/validation.md +116 -116
  18. package/.agent-context/skills/backend.md +28 -28
  19. package/.agent-context/skills/cli/README.md +55 -49
  20. package/.agent-context/skills/cli/compatibility-manifest.json +8 -8
  21. package/.agent-context/skills/cli/init.md +37 -37
  22. package/.agent-context/skills/cli/output.md +35 -35
  23. package/.agent-context/skills/cli/safety-telemetry.md +39 -0
  24. package/.agent-context/skills/cli/upgrade.md +37 -37
  25. package/.agent-context/skills/cli.md +31 -28
  26. package/.agent-context/skills/distribution/.evidence/compatibility-manifest.json +9 -0
  27. package/.agent-context/skills/distribution/.evidence/sbom-excerpt.json +6 -0
  28. package/.agent-context/skills/distribution/.evidence/test-report.json +8 -0
  29. package/.agent-context/skills/distribution/CHANGELOG.md +7 -0
  30. package/.agent-context/skills/distribution/README.md +27 -19
  31. package/.agent-context/skills/distribution/compatibility-manifest.json +8 -8
  32. package/.agent-context/skills/distribution/compatibility.md +31 -31
  33. package/.agent-context/skills/distribution/package.json +5 -0
  34. package/.agent-context/skills/distribution/provenance-attestation.md +47 -0
  35. package/.agent-context/skills/distribution/publish.md +36 -36
  36. package/.agent-context/skills/distribution/rollback.md +31 -31
  37. package/.agent-context/skills/distribution/tests/.gitkeep +1 -0
  38. package/.agent-context/skills/distribution.md +31 -28
  39. package/.agent-context/skills/frontend/.evidence/compatibility-manifest.json +9 -0
  40. package/.agent-context/skills/frontend/.evidence/sbom-excerpt.json +6 -0
  41. package/.agent-context/skills/frontend/.evidence/test-report.json +8 -0
  42. package/.agent-context/skills/frontend/CHANGELOG.md +7 -0
  43. package/.agent-context/skills/frontend/README.md +49 -36
  44. package/.agent-context/skills/frontend/accessibility.md +107 -107
  45. package/.agent-context/skills/frontend/compatibility-manifest.json +8 -8
  46. package/.agent-context/skills/frontend/conversion-clarity.md +51 -0
  47. package/.agent-context/skills/frontend/motion.md +66 -66
  48. package/.agent-context/skills/frontend/package.json +5 -0
  49. package/.agent-context/skills/frontend/performance.md +62 -62
  50. package/.agent-context/skills/frontend/responsive-delivery.md +41 -0
  51. package/.agent-context/skills/frontend/tests/.gitkeep +1 -0
  52. package/.agent-context/skills/frontend/ui-architecture.md +128 -128
  53. package/.agent-context/skills/frontend.md +35 -29
  54. package/.agent-context/skills/fullstack/.evidence/compatibility-manifest.json +9 -0
  55. package/.agent-context/skills/fullstack/.evidence/sbom-excerpt.json +6 -0
  56. package/.agent-context/skills/fullstack/.evidence/test-report.json +8 -0
  57. package/.agent-context/skills/fullstack/CHANGELOG.md +7 -0
  58. package/.agent-context/skills/fullstack/README.md +27 -19
  59. package/.agent-context/skills/fullstack/compatibility-manifest.json +8 -8
  60. package/.agent-context/skills/fullstack/contracts.md +52 -52
  61. package/.agent-context/skills/fullstack/end-to-end.md +41 -41
  62. package/.agent-context/skills/fullstack/feature-slicing.md +64 -64
  63. package/.agent-context/skills/fullstack/package.json +5 -0
  64. package/.agent-context/skills/fullstack/release-coordination.md +51 -0
  65. package/.agent-context/skills/fullstack/tests/.gitkeep +1 -0
  66. package/.agent-context/skills/fullstack.md +29 -26
  67. package/.agent-context/skills/index.json +107 -107
  68. package/.agent-context/skills/review-quality/.evidence/compatibility-manifest.json +9 -0
  69. package/.agent-context/skills/review-quality/.evidence/sbom-excerpt.json +6 -0
  70. package/.agent-context/skills/review-quality/.evidence/test-report.json +8 -0
  71. package/.agent-context/skills/review-quality/CHANGELOG.md +7 -0
  72. package/.agent-context/skills/review-quality/README.md +27 -19
  73. package/.agent-context/skills/review-quality/benchmark.md +29 -29
  74. package/.agent-context/skills/review-quality/compatibility-manifest.json +8 -8
  75. package/.agent-context/skills/review-quality/package.json +5 -0
  76. package/.agent-context/skills/review-quality/planning.md +37 -37
  77. package/.agent-context/skills/review-quality/release-decision.md +49 -0
  78. package/.agent-context/skills/review-quality/security.md +33 -33
  79. package/.agent-context/skills/review-quality/tests/.gitkeep +1 -0
  80. package/.agent-context/skills/review-quality.md +33 -27
  81. package/.agent-context/stacks/flutter.md +16 -16
  82. package/.agent-context/stacks/react-native.md +16 -16
  83. package/.agent-context/state/architecture-map.md +25 -25
  84. package/.agent-context/state/benchmark-analysis.json +431 -431
  85. package/.agent-context/state/benchmark-thresholds.json +10 -10
  86. package/.agent-context/state/benchmark-watchlist.json +19 -19
  87. package/.agent-context/state/dependency-map.md +32 -32
  88. package/.agent-context/state/quality-trend-report.json +16 -6
  89. package/.agent-context/state/skill-platform.json +38 -38
  90. package/.agent-context/state/weekly-governance-report.json +126 -0
  91. package/.agent-override.md +36 -36
  92. package/.cursorrules +1 -1
  93. package/.gemini/instructions.md +20 -20
  94. package/.github/ISSUE_TEMPLATE/v1.7-frontend-work-item.yml +54 -54
  95. package/.github/copilot-instructions.md +21 -21
  96. package/.github/workflows/benchmark-detection.yml +38 -38
  97. package/.github/workflows/benchmark-intelligence.yml +50 -50
  98. package/.github/workflows/frontend-usability-gate.yml +36 -36
  99. package/.github/workflows/governance-weekly-report.yml +43 -0
  100. package/.github/workflows/release-gate.yml +32 -32
  101. package/.github/workflows/sbom-compliance.yml +32 -32
  102. package/.windsurfrules +1 -1
  103. package/AGENTS.md +27 -27
  104. package/README.md +389 -368
  105. package/lib/cli/commands/init.mjs +13 -1
  106. package/lib/cli/commands/optimize.mjs +171 -171
  107. package/lib/cli/commands/upgrade.mjs +9 -1
  108. package/lib/cli/compatibility.mjs +124 -124
  109. package/lib/cli/constants.mjs +37 -2
  110. package/lib/cli/token-optimization.mjs +275 -275
  111. package/lib/cli/utils.mjs +24 -3
  112. package/mcp.json +92 -92
  113. package/package.json +2 -1
  114. package/scripts/benchmark-gate.mjs +121 -121
  115. package/scripts/benchmark-intelligence.mjs +140 -140
  116. package/scripts/detection-benchmark.mjs +138 -138
  117. package/scripts/frontend-usability-audit.mjs +87 -87
  118. package/scripts/generate-sbom.mjs +61 -61
  119. package/scripts/governance-weekly-report.mjs +293 -0
  120. package/scripts/init-project.ps1 +104 -104
  121. package/scripts/llm-judge.mjs +664 -664
  122. package/scripts/quality-trend-report.mjs +288 -288
  123. package/scripts/release-gate.mjs +261 -259
  124. package/scripts/skill-tier-policy.mjs +75 -75
  125. package/scripts/token-optimization-benchmark.mjs +252 -252
  126. package/scripts/validate.mjs +942 -865
@@ -1,259 +1,261 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * release-gate.mjs
5
- *
6
- * Enterprise release gate for V1.8.
7
- * Produces machine-readable output for CI and fails fast on missing release evidence.
8
- */
9
-
10
- import { existsSync, readFileSync } from 'node:fs';
11
- import { resolve, dirname } from 'node:path';
12
- import { fileURLToPath } from 'node:url';
13
- import { execFileSync } from 'node:child_process';
14
-
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = dirname(__filename);
17
- const REPOSITORY_ROOT = resolve(__dirname, '..');
18
-
19
- const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
20
- const NODE_MIN_PATTERN = /^\d+(\.\d+)?$/;
21
- const SUPPORTED_COMPATIBILITY_PLATFORMS = new Set(['windows', 'linux', 'macos']);
22
- const REQUIRED_SKILL_DOMAINS = [
23
- 'backend',
24
- 'frontend',
25
- 'fullstack',
26
- 'cli',
27
- 'distribution',
28
- 'review-quality',
29
- ];
30
- const FRONTEND_PARITY_CHECKLIST_PATH = '.agent-context/review-checklists/frontend-skill-parity.md';
31
- const FRONTEND_AUDIT_SCRIPT_PATH = 'scripts/frontend-usability-audit.mjs';
32
- const REQUIRED_FRONTEND_PARITY_SNIPPETS = [
33
- 'Architecture and Composition',
34
- 'Interaction and Motion',
35
- 'Accessibility and Responsiveness',
36
- 'UX Narrative and Conversion Clarity',
37
- 'Release Evidence',
38
- ];
39
-
40
- function readText(relativeFilePath) {
41
- const absolutePath = resolve(REPOSITORY_ROOT, relativeFilePath);
42
- if (!existsSync(absolutePath)) {
43
- return '';
44
- }
45
-
46
- return readFileSync(absolutePath, 'utf8');
47
- }
48
-
49
- function pushResult(results, isPassed, checkName, details) {
50
- results.push({
51
- checkName,
52
- passed: isPassed,
53
- details,
54
- });
55
- }
56
-
57
- function validateCompatibilityManifestShape(parsedManifest, skillDomainName) {
58
- const validationErrors = [];
59
-
60
- if (!Array.isArray(parsedManifest.ides) || parsedManifest.ides.length === 0) {
61
- validationErrors.push(`Domain ${skillDomainName} must define non-empty ides[]`);
62
- }
63
-
64
- if (!Array.isArray(parsedManifest.platforms) || parsedManifest.platforms.length === 0) {
65
- validationErrors.push(`Domain ${skillDomainName} must define non-empty platforms[]`);
66
- } else {
67
- const unsupportedPlatformName = parsedManifest.platforms.find(
68
- (platformName) => !SUPPORTED_COMPATIBILITY_PLATFORMS.has(platformName)
69
- );
70
-
71
- if (unsupportedPlatformName) {
72
- validationErrors.push(`Domain ${skillDomainName} has unsupported platform: ${unsupportedPlatformName}`);
73
- }
74
- }
75
-
76
- if (typeof parsedManifest.nodeMin !== 'string' || !NODE_MIN_PATTERN.test(parsedManifest.nodeMin)) {
77
- validationErrors.push(`Domain ${skillDomainName} must define nodeMin as "18" or "18.0" style string`);
78
- }
79
-
80
- return validationErrors;
81
- }
82
-
83
- function runReleaseGate() {
84
- const results = [];
85
- const packageJsonPath = 'package.json';
86
- const changelogPath = 'CHANGELOG.md';
87
- const roadmapPath = 'docs/roadmap.md';
88
-
89
- const packageJsonContent = readText(packageJsonPath);
90
- if (!packageJsonContent) {
91
- pushResult(results, false, 'package-json-exists', `Missing ${packageJsonPath}`);
92
- }
93
-
94
- let packageManifest = null;
95
- if (packageJsonContent) {
96
- try {
97
- packageManifest = JSON.parse(packageJsonContent);
98
- pushResult(results, true, 'package-json-parse', 'package.json is valid JSON');
99
- } catch (packageParseError) {
100
- const parseMessage = packageParseError instanceof Error ? packageParseError.message : 'Unknown parse error';
101
- pushResult(results, false, 'package-json-parse', `Cannot parse package.json: ${parseMessage}`);
102
- }
103
- }
104
-
105
- const releaseVersion = packageManifest?.version;
106
- if (!releaseVersion || !VERSION_PATTERN.test(releaseVersion)) {
107
- pushResult(results, false, 'version-semver', `Invalid package version: ${String(releaseVersion)}`);
108
- } else {
109
- pushResult(results, true, 'version-semver', `Version ${releaseVersion} matches x.y.z format`);
110
- }
111
-
112
- const changelogContent = readText(changelogPath);
113
- if (!changelogContent) {
114
- pushResult(results, false, 'changelog-exists', `Missing ${changelogPath}`);
115
- } else if (!releaseVersion) {
116
- pushResult(results, false, 'changelog-version-entry', 'Cannot check changelog because version is invalid');
117
- } else if (!changelogContent.includes(`## ${releaseVersion} - `)) {
118
- pushResult(results, false, 'changelog-version-entry', `Missing release header for ${releaseVersion} in CHANGELOG.md`);
119
- } else {
120
- pushResult(results, true, 'changelog-version-entry', `Found release header for ${releaseVersion}`);
121
- }
122
-
123
- const roadmapContent = readText(roadmapPath);
124
- if (!roadmapContent) {
125
- pushResult(results, false, 'roadmap-exists', `Missing ${roadmapPath}`);
126
- } else if (!roadmapContent.includes('V1.8')) {
127
- pushResult(results, false, 'roadmap-v18', 'Roadmap does not mention V1.8 release track');
128
- } else {
129
- pushResult(results, true, 'roadmap-v18', 'Roadmap includes V1.8 release track');
130
- }
131
-
132
- const requiredEnterpriseFiles = [
133
- '.agent-context/review-checklists/release-operations.md',
134
- 'docs/v1.8-operations-playbook.md',
135
- '.github/workflows/release-gate.yml',
136
- '.github/workflows/sbom-compliance.yml',
137
- ];
138
-
139
- for (const requiredEnterpriseFile of requiredEnterpriseFiles) {
140
- const absoluteRequiredPath = resolve(REPOSITORY_ROOT, requiredEnterpriseFile);
141
- if (!existsSync(absoluteRequiredPath)) {
142
- pushResult(results, false, 'required-enterprise-file', `Missing ${requiredEnterpriseFile}`);
143
- continue;
144
- }
145
-
146
- pushResult(results, true, 'required-enterprise-file', `${requiredEnterpriseFile} is present`);
147
- }
148
-
149
- let validatedCompatibilityManifestCount = 0;
150
-
151
- for (const skillDomainName of REQUIRED_SKILL_DOMAINS) {
152
- const compatibilityManifestPath = `.agent-context/skills/${skillDomainName}/compatibility-manifest.json`;
153
- const compatibilityManifestContent = readText(compatibilityManifestPath);
154
-
155
- if (!compatibilityManifestContent) {
156
- pushResult(results, false, 'compatibility-manifest', `Missing ${compatibilityManifestPath}`);
157
- continue;
158
- }
159
-
160
- let parsedCompatibilityManifest;
161
- try {
162
- parsedCompatibilityManifest = JSON.parse(compatibilityManifestContent);
163
- } catch (compatibilityManifestParseError) {
164
- const parseErrorMessage = compatibilityManifestParseError instanceof Error
165
- ? compatibilityManifestParseError.message
166
- : 'Unknown parse error';
167
- pushResult(results, false, 'compatibility-manifest', `Invalid JSON in ${compatibilityManifestPath}: ${parseErrorMessage}`);
168
- continue;
169
- }
170
-
171
- const compatibilityValidationErrors = validateCompatibilityManifestShape(
172
- parsedCompatibilityManifest,
173
- skillDomainName
174
- );
175
-
176
- if (compatibilityValidationErrors.length > 0) {
177
- pushResult(results, false, 'compatibility-manifest', compatibilityValidationErrors.join('; '));
178
- continue;
179
- }
180
-
181
- validatedCompatibilityManifestCount += 1;
182
- pushResult(results, true, 'compatibility-manifest', `${compatibilityManifestPath} is valid`);
183
- }
184
-
185
- if (validatedCompatibilityManifestCount === REQUIRED_SKILL_DOMAINS.length) {
186
- pushResult(
187
- results,
188
- true,
189
- 'compatibility-manifest-coverage',
190
- `Validated ${validatedCompatibilityManifestCount}/${REQUIRED_SKILL_DOMAINS.length} required skill compatibility manifests`
191
- );
192
- } else {
193
- pushResult(
194
- results,
195
- false,
196
- 'compatibility-manifest-coverage',
197
- `Validated ${validatedCompatibilityManifestCount}/${REQUIRED_SKILL_DOMAINS.length} required skill compatibility manifests`
198
- );
199
- }
200
-
201
- const frontendParityChecklistContent = readText(FRONTEND_PARITY_CHECKLIST_PATH);
202
- if (!frontendParityChecklistContent) {
203
- pushResult(results, false, 'frontend-parity-checklist-exists', `Missing ${FRONTEND_PARITY_CHECKLIST_PATH}`);
204
- } else {
205
- pushResult(results, true, 'frontend-parity-checklist-exists', `${FRONTEND_PARITY_CHECKLIST_PATH} is present`);
206
-
207
- const missingFrontendParitySnippets = REQUIRED_FRONTEND_PARITY_SNIPPETS.filter(
208
- (requiredSnippet) => !frontendParityChecklistContent.includes(requiredSnippet)
209
- );
210
-
211
- if (missingFrontendParitySnippets.length === 0) {
212
- pushResult(results, true, 'frontend-parity-checklist-coverage', 'Frontend parity checklist sections are complete');
213
- } else {
214
- pushResult(
215
- results,
216
- false,
217
- 'frontend-parity-checklist-coverage',
218
- `Missing frontend parity checklist sections: ${missingFrontendParitySnippets.join(', ')}`
219
- );
220
- }
221
- }
222
-
223
- try {
224
- const frontendAuditRawOutput = execFileSync('node', [FRONTEND_AUDIT_SCRIPT_PATH], {
225
- cwd: REPOSITORY_ROOT,
226
- encoding: 'utf8',
227
- maxBuffer: 1024 * 1024,
228
- });
229
- const frontendAuditReport = JSON.parse(frontendAuditRawOutput);
230
-
231
- if (frontendAuditReport.passed === true) {
232
- pushResult(results, true, 'frontend-usability-audit', 'frontend-usability-audit report passed');
233
- } else {
234
- const failureDetails = Array.isArray(frontendAuditReport.failures)
235
- ? frontendAuditReport.failures.join('; ')
236
- : 'Unknown frontend audit failures';
237
- pushResult(results, false, 'frontend-usability-audit', `frontend-usability-audit reported failures: ${failureDetails}`);
238
- }
239
- } catch (frontendAuditError) {
240
- const frontendAuditErrorMessage = frontendAuditError instanceof Error
241
- ? frontendAuditError.message
242
- : 'Unknown frontend audit execution error';
243
- pushResult(results, false, 'frontend-usability-audit', `Failed to execute frontend usability audit: ${frontendAuditErrorMessage}`);
244
- }
245
-
246
- const failureCount = results.filter((checkResult) => !checkResult.passed).length;
247
- const releaseGateReport = {
248
- generatedAt: new Date().toISOString(),
249
- gateName: 'release-gate',
250
- passed: failureCount === 0,
251
- failureCount,
252
- results,
253
- };
254
-
255
- console.log(JSON.stringify(releaseGateReport, null, 2));
256
- process.exit(releaseGateReport.passed ? 0 : 1);
257
- }
258
-
259
- runReleaseGate();
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * release-gate.mjs
5
+ *
6
+ * Enterprise release gate for V1.8.
7
+ * Produces machine-readable output for CI and fails fast on missing release evidence.
8
+ */
9
+
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { resolve, dirname } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { execFileSync } from 'node:child_process';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+ const REPOSITORY_ROOT = resolve(__dirname, '..');
18
+
19
+ const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
20
+ const NODE_MIN_PATTERN = /^\d+(\.\d+)?$/;
21
+ const SUPPORTED_COMPATIBILITY_PLATFORMS = new Set(['windows', 'linux', 'macos']);
22
+ const REQUIRED_SKILL_DOMAINS = [
23
+ 'backend',
24
+ 'frontend',
25
+ 'fullstack',
26
+ 'cli',
27
+ 'distribution',
28
+ 'review-quality',
29
+ ];
30
+ const FRONTEND_PARITY_CHECKLIST_PATH = '.agent-context/review-checklists/frontend-skill-parity.md';
31
+ const FRONTEND_AUDIT_SCRIPT_PATH = 'scripts/frontend-usability-audit.mjs';
32
+ const REQUIRED_FRONTEND_PARITY_SNIPPETS = [
33
+ 'Architecture and Composition',
34
+ 'Interaction and Motion',
35
+ 'Accessibility and Responsiveness',
36
+ 'UX Narrative and Conversion Clarity',
37
+ 'Release Evidence',
38
+ ];
39
+
40
+ function readText(relativeFilePath) {
41
+ const absolutePath = resolve(REPOSITORY_ROOT, relativeFilePath);
42
+ if (!existsSync(absolutePath)) {
43
+ return '';
44
+ }
45
+
46
+ return readFileSync(absolutePath, 'utf8');
47
+ }
48
+
49
+ function pushResult(results, isPassed, checkName, details) {
50
+ results.push({
51
+ checkName,
52
+ passed: isPassed,
53
+ details,
54
+ });
55
+ }
56
+
57
+ function validateCompatibilityManifestShape(parsedManifest, skillDomainName) {
58
+ const validationErrors = [];
59
+
60
+ if (!Array.isArray(parsedManifest.ides) || parsedManifest.ides.length === 0) {
61
+ validationErrors.push(`Domain ${skillDomainName} must define non-empty ides[]`);
62
+ }
63
+
64
+ if (!Array.isArray(parsedManifest.platforms) || parsedManifest.platforms.length === 0) {
65
+ validationErrors.push(`Domain ${skillDomainName} must define non-empty platforms[]`);
66
+ } else {
67
+ const unsupportedPlatformName = parsedManifest.platforms.find(
68
+ (platformName) => !SUPPORTED_COMPATIBILITY_PLATFORMS.has(platformName)
69
+ );
70
+
71
+ if (unsupportedPlatformName) {
72
+ validationErrors.push(`Domain ${skillDomainName} has unsupported platform: ${unsupportedPlatformName}`);
73
+ }
74
+ }
75
+
76
+ if (typeof parsedManifest.nodeMin !== 'string' || !NODE_MIN_PATTERN.test(parsedManifest.nodeMin)) {
77
+ validationErrors.push(`Domain ${skillDomainName} must define nodeMin as "18" or "18.0" style string`);
78
+ }
79
+
80
+ return validationErrors;
81
+ }
82
+
83
+ function runReleaseGate() {
84
+ const results = [];
85
+ const packageJsonPath = 'package.json';
86
+ const changelogPath = 'CHANGELOG.md';
87
+ const roadmapPath = 'docs/roadmap.md';
88
+
89
+ const packageJsonContent = readText(packageJsonPath);
90
+ if (!packageJsonContent) {
91
+ pushResult(results, false, 'package-json-exists', `Missing ${packageJsonPath}`);
92
+ }
93
+
94
+ let packageManifest = null;
95
+ if (packageJsonContent) {
96
+ try {
97
+ packageManifest = JSON.parse(packageJsonContent);
98
+ pushResult(results, true, 'package-json-parse', 'package.json is valid JSON');
99
+ } catch (packageParseError) {
100
+ const parseMessage = packageParseError instanceof Error ? packageParseError.message : 'Unknown parse error';
101
+ pushResult(results, false, 'package-json-parse', `Cannot parse package.json: ${parseMessage}`);
102
+ }
103
+ }
104
+
105
+ const releaseVersion = packageManifest?.version;
106
+ if (!releaseVersion || !VERSION_PATTERN.test(releaseVersion)) {
107
+ pushResult(results, false, 'version-semver', `Invalid package version: ${String(releaseVersion)}`);
108
+ } else {
109
+ pushResult(results, true, 'version-semver', `Version ${releaseVersion} matches x.y.z format`);
110
+ }
111
+
112
+ const changelogContent = readText(changelogPath);
113
+ if (!changelogContent) {
114
+ pushResult(results, false, 'changelog-exists', `Missing ${changelogPath}`);
115
+ } else if (!releaseVersion) {
116
+ pushResult(results, false, 'changelog-version-entry', 'Cannot check changelog because version is invalid');
117
+ } else if (!changelogContent.includes(`## ${releaseVersion} - `)) {
118
+ pushResult(results, false, 'changelog-version-entry', `Missing release header for ${releaseVersion} in CHANGELOG.md`);
119
+ } else {
120
+ pushResult(results, true, 'changelog-version-entry', `Found release header for ${releaseVersion}`);
121
+ }
122
+
123
+ const roadmapContent = readText(roadmapPath);
124
+ if (!roadmapContent) {
125
+ pushResult(results, false, 'roadmap-exists', `Missing ${roadmapPath}`);
126
+ } else if (!roadmapContent.includes('V1.8')) {
127
+ pushResult(results, false, 'roadmap-v18', 'Roadmap does not mention V1.8 release track');
128
+ } else {
129
+ pushResult(results, true, 'roadmap-v18', 'Roadmap includes V1.8 release track');
130
+ }
131
+
132
+ const requiredEnterpriseFiles = [
133
+ '.agent-context/review-checklists/release-operations.md',
134
+ 'docs/v1.8-operations-playbook.md',
135
+ '.github/workflows/release-gate.yml',
136
+ '.github/workflows/sbom-compliance.yml',
137
+ '.github/workflows/governance-weekly-report.yml',
138
+ 'scripts/governance-weekly-report.mjs',
139
+ ];
140
+
141
+ for (const requiredEnterpriseFile of requiredEnterpriseFiles) {
142
+ const absoluteRequiredPath = resolve(REPOSITORY_ROOT, requiredEnterpriseFile);
143
+ if (!existsSync(absoluteRequiredPath)) {
144
+ pushResult(results, false, 'required-enterprise-file', `Missing ${requiredEnterpriseFile}`);
145
+ continue;
146
+ }
147
+
148
+ pushResult(results, true, 'required-enterprise-file', `${requiredEnterpriseFile} is present`);
149
+ }
150
+
151
+ let validatedCompatibilityManifestCount = 0;
152
+
153
+ for (const skillDomainName of REQUIRED_SKILL_DOMAINS) {
154
+ const compatibilityManifestPath = `.agent-context/skills/${skillDomainName}/compatibility-manifest.json`;
155
+ const compatibilityManifestContent = readText(compatibilityManifestPath);
156
+
157
+ if (!compatibilityManifestContent) {
158
+ pushResult(results, false, 'compatibility-manifest', `Missing ${compatibilityManifestPath}`);
159
+ continue;
160
+ }
161
+
162
+ let parsedCompatibilityManifest;
163
+ try {
164
+ parsedCompatibilityManifest = JSON.parse(compatibilityManifestContent);
165
+ } catch (compatibilityManifestParseError) {
166
+ const parseErrorMessage = compatibilityManifestParseError instanceof Error
167
+ ? compatibilityManifestParseError.message
168
+ : 'Unknown parse error';
169
+ pushResult(results, false, 'compatibility-manifest', `Invalid JSON in ${compatibilityManifestPath}: ${parseErrorMessage}`);
170
+ continue;
171
+ }
172
+
173
+ const compatibilityValidationErrors = validateCompatibilityManifestShape(
174
+ parsedCompatibilityManifest,
175
+ skillDomainName
176
+ );
177
+
178
+ if (compatibilityValidationErrors.length > 0) {
179
+ pushResult(results, false, 'compatibility-manifest', compatibilityValidationErrors.join('; '));
180
+ continue;
181
+ }
182
+
183
+ validatedCompatibilityManifestCount += 1;
184
+ pushResult(results, true, 'compatibility-manifest', `${compatibilityManifestPath} is valid`);
185
+ }
186
+
187
+ if (validatedCompatibilityManifestCount === REQUIRED_SKILL_DOMAINS.length) {
188
+ pushResult(
189
+ results,
190
+ true,
191
+ 'compatibility-manifest-coverage',
192
+ `Validated ${validatedCompatibilityManifestCount}/${REQUIRED_SKILL_DOMAINS.length} required skill compatibility manifests`
193
+ );
194
+ } else {
195
+ pushResult(
196
+ results,
197
+ false,
198
+ 'compatibility-manifest-coverage',
199
+ `Validated ${validatedCompatibilityManifestCount}/${REQUIRED_SKILL_DOMAINS.length} required skill compatibility manifests`
200
+ );
201
+ }
202
+
203
+ const frontendParityChecklistContent = readText(FRONTEND_PARITY_CHECKLIST_PATH);
204
+ if (!frontendParityChecklistContent) {
205
+ pushResult(results, false, 'frontend-parity-checklist-exists', `Missing ${FRONTEND_PARITY_CHECKLIST_PATH}`);
206
+ } else {
207
+ pushResult(results, true, 'frontend-parity-checklist-exists', `${FRONTEND_PARITY_CHECKLIST_PATH} is present`);
208
+
209
+ const missingFrontendParitySnippets = REQUIRED_FRONTEND_PARITY_SNIPPETS.filter(
210
+ (requiredSnippet) => !frontendParityChecklistContent.includes(requiredSnippet)
211
+ );
212
+
213
+ if (missingFrontendParitySnippets.length === 0) {
214
+ pushResult(results, true, 'frontend-parity-checklist-coverage', 'Frontend parity checklist sections are complete');
215
+ } else {
216
+ pushResult(
217
+ results,
218
+ false,
219
+ 'frontend-parity-checklist-coverage',
220
+ `Missing frontend parity checklist sections: ${missingFrontendParitySnippets.join(', ')}`
221
+ );
222
+ }
223
+ }
224
+
225
+ try {
226
+ const frontendAuditRawOutput = execFileSync('node', [FRONTEND_AUDIT_SCRIPT_PATH], {
227
+ cwd: REPOSITORY_ROOT,
228
+ encoding: 'utf8',
229
+ maxBuffer: 1024 * 1024,
230
+ });
231
+ const frontendAuditReport = JSON.parse(frontendAuditRawOutput);
232
+
233
+ if (frontendAuditReport.passed === true) {
234
+ pushResult(results, true, 'frontend-usability-audit', 'frontend-usability-audit report passed');
235
+ } else {
236
+ const failureDetails = Array.isArray(frontendAuditReport.failures)
237
+ ? frontendAuditReport.failures.join('; ')
238
+ : 'Unknown frontend audit failures';
239
+ pushResult(results, false, 'frontend-usability-audit', `frontend-usability-audit reported failures: ${failureDetails}`);
240
+ }
241
+ } catch (frontendAuditError) {
242
+ const frontendAuditErrorMessage = frontendAuditError instanceof Error
243
+ ? frontendAuditError.message
244
+ : 'Unknown frontend audit execution error';
245
+ pushResult(results, false, 'frontend-usability-audit', `Failed to execute frontend usability audit: ${frontendAuditErrorMessage}`);
246
+ }
247
+
248
+ const failureCount = results.filter((checkResult) => !checkResult.passed).length;
249
+ const releaseGateReport = {
250
+ generatedAt: new Date().toISOString(),
251
+ gateName: 'release-gate',
252
+ passed: failureCount === 0,
253
+ failureCount,
254
+ results,
255
+ };
256
+
257
+ console.log(JSON.stringify(releaseGateReport, null, 2));
258
+ process.exit(releaseGateReport.passed ? 0 : 1);
259
+ }
260
+
261
+ runReleaseGate();