gorsee 0.2.11 → 0.2.13
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.
- package/README.md +52 -4
- package/dist-pkg/ai/bundle.d.ts +1 -0
- package/dist-pkg/ai/framework-context.d.ts +2 -0
- package/dist-pkg/ai/framework-context.js +6 -1
- package/dist-pkg/ai/ide.d.ts +1 -0
- package/dist-pkg/ai/ide.js +3 -0
- package/dist-pkg/ai/index.d.ts +10 -1
- package/dist-pkg/ai/index.js +13 -2
- package/dist-pkg/ai/mcp.js +4 -0
- package/dist-pkg/ai/session-pack.d.ts +8 -0
- package/dist-pkg/ai/session-pack.js +51 -1
- package/dist-pkg/ai/store.d.ts +25 -1
- package/dist-pkg/ai/store.js +89 -3
- package/dist-pkg/ai/summary.d.ts +88 -0
- package/dist-pkg/ai/summary.js +310 -1
- package/dist-pkg/build/manifest.d.ts +4 -2
- package/dist-pkg/build/manifest.js +32 -2
- package/dist-pkg/cli/cmd-ai.js +66 -0
- package/dist-pkg/cli/cmd-build.js +72 -26
- package/dist-pkg/cli/cmd-check.js +104 -11
- package/dist-pkg/cli/cmd-create.js +333 -7
- package/dist-pkg/cli/cmd-deploy.js +17 -3
- package/dist-pkg/cli/cmd-docs.d.ts +3 -1
- package/dist-pkg/cli/cmd-docs.js +5 -3
- package/dist-pkg/cli/cmd-start.js +8 -1
- package/dist-pkg/cli/cmd-upgrade.d.ts +3 -0
- package/dist-pkg/cli/cmd-upgrade.js +14 -2
- package/dist-pkg/cli/cmd-worker.d.ts +9 -0
- package/dist-pkg/cli/cmd-worker.js +78 -0
- package/dist-pkg/cli/framework-md.js +16 -4
- package/dist-pkg/cli/index.js +5 -0
- package/dist-pkg/runtime/app-config.d.ts +5 -0
- package/dist-pkg/runtime/app-config.js +26 -5
- package/dist-pkg/runtime/typed-routes.js +3 -4
- package/dist-pkg/server/index.d.ts +2 -1
- package/dist-pkg/server/index.js +1 -0
- package/dist-pkg/server/jobs.d.ts +35 -1
- package/dist-pkg/server/jobs.js +226 -3
- package/dist-pkg/server/manifest.d.ts +30 -0
- package/dist-pkg/server/manifest.js +30 -1
- package/dist-pkg/server/redis-client.d.ts +9 -0
- package/dist-pkg/server/redis-client.js +4 -1
- package/dist-pkg/server/redis-job-queue.d.ts +2 -0
- package/dist-pkg/server/redis-job-queue.js +434 -16
- package/dist-pkg/server/worker-service.d.ts +33 -0
- package/dist-pkg/server/worker-service.js +135 -0
- package/dist-pkg/server-entry.d.ts +2 -1
- package/dist-pkg/server-entry.js +4 -0
- package/package.json +3 -3
package/dist-pkg/ai/summary.d.ts
CHANGED
|
@@ -4,12 +4,38 @@ import type { ReactiveTraceArtifact } from "../reactive/diagnostics.js";
|
|
|
4
4
|
export interface AIContextPacket {
|
|
5
5
|
schemaVersion: string;
|
|
6
6
|
generatedAt: string;
|
|
7
|
+
app?: {
|
|
8
|
+
mode: "frontend" | "fullstack" | "server";
|
|
9
|
+
runtimeTopology: "single-instance" | "multi-instance";
|
|
10
|
+
};
|
|
7
11
|
summary: {
|
|
8
12
|
headline: string;
|
|
9
13
|
events: number;
|
|
10
14
|
errors: number;
|
|
11
15
|
warnings: number;
|
|
12
16
|
};
|
|
17
|
+
readiness: {
|
|
18
|
+
deploy: {
|
|
19
|
+
status: "ready" | "caution" | "blocked";
|
|
20
|
+
reasons: string[];
|
|
21
|
+
};
|
|
22
|
+
scaling: {
|
|
23
|
+
status: "ready" | "caution" | "blocked" | "not-applicable";
|
|
24
|
+
reasons: string[];
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
release?: {
|
|
28
|
+
appMode: "frontend" | "fullstack" | "server";
|
|
29
|
+
runtimeKind: "frontend-static" | "fullstack-runtime" | "server-runtime";
|
|
30
|
+
processEntrypoints: string[];
|
|
31
|
+
handlerEntrypoints: string[];
|
|
32
|
+
workerEntrypoint?: string;
|
|
33
|
+
routeCount: number;
|
|
34
|
+
clientAssetCount: number;
|
|
35
|
+
prerenderedCount: number;
|
|
36
|
+
serverEntryCount: number;
|
|
37
|
+
generatedAt: string;
|
|
38
|
+
};
|
|
13
39
|
latestDiagnostic?: Partial<AIDiagnostic>;
|
|
14
40
|
recentIncidents: Array<{
|
|
15
41
|
ts: string;
|
|
@@ -53,5 +79,67 @@ export interface AIContextPacket {
|
|
|
53
79
|
};
|
|
54
80
|
recommendations: string[];
|
|
55
81
|
}
|
|
82
|
+
export interface AIReleaseBrief {
|
|
83
|
+
schemaVersion: string;
|
|
84
|
+
generatedAt: string;
|
|
85
|
+
app?: AIContextPacket["app"];
|
|
86
|
+
release?: AIContextPacket["release"];
|
|
87
|
+
readiness: AIContextPacket["readiness"];
|
|
88
|
+
verdict: "ship" | "review" | "hold";
|
|
89
|
+
headline: string;
|
|
90
|
+
blockers: string[];
|
|
91
|
+
cautions: string[];
|
|
92
|
+
recommendations: string[];
|
|
93
|
+
}
|
|
94
|
+
export interface AIIncidentBrief {
|
|
95
|
+
schemaVersion: string;
|
|
96
|
+
generatedAt: string;
|
|
97
|
+
app?: AIContextPacket["app"];
|
|
98
|
+
release?: AIContextPacket["release"];
|
|
99
|
+
readiness: AIContextPacket["readiness"];
|
|
100
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
101
|
+
headline: string;
|
|
102
|
+
incidents: AIContextPacket["recentIncidents"];
|
|
103
|
+
clusters: AIContextPacket["incidentClusters"];
|
|
104
|
+
artifactRegressions: AIContextPacket["artifactRegressions"];
|
|
105
|
+
recommendations: string[];
|
|
106
|
+
}
|
|
107
|
+
export interface AIDeploySummary {
|
|
108
|
+
schemaVersion: string;
|
|
109
|
+
generatedAt: string;
|
|
110
|
+
app?: AIContextPacket["app"];
|
|
111
|
+
release?: AIContextPacket["release"];
|
|
112
|
+
readiness: AIContextPacket["readiness"];
|
|
113
|
+
status: "ready" | "review" | "blocked";
|
|
114
|
+
headline: string;
|
|
115
|
+
processEntrypoints: string[];
|
|
116
|
+
handlerEntrypoints: string[];
|
|
117
|
+
workerEntrypoint?: string;
|
|
118
|
+
artifactRegressions: AIContextPacket["artifactRegressions"];
|
|
119
|
+
recommendations: string[];
|
|
120
|
+
}
|
|
121
|
+
export interface AIIncidentSnapshot {
|
|
122
|
+
schemaVersion: string;
|
|
123
|
+
generatedAt: string;
|
|
124
|
+
app?: AIContextPacket["app"];
|
|
125
|
+
release?: AIContextPacket["release"];
|
|
126
|
+
readiness: AIContextPacket["readiness"];
|
|
127
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
128
|
+
headline: string;
|
|
129
|
+
latestIncident?: AIContextPacket["recentIncidents"][number];
|
|
130
|
+
incidentCount: number;
|
|
131
|
+
clusterCount: number;
|
|
132
|
+
clusters: AIContextPacket["incidentClusters"];
|
|
133
|
+
hotspots: AIContextPacket["hotspots"];
|
|
134
|
+
recommendations: string[];
|
|
135
|
+
}
|
|
56
136
|
export declare function createAIContextPacket(report: AIHealthReport, events: AIEvent[], latestDiagnostic?: Partial<AIDiagnostic>, reactiveTrace?: ReactiveTraceArtifact | null): AIContextPacket;
|
|
57
137
|
export declare function renderAIContextMarkdown(packet: AIContextPacket): string;
|
|
138
|
+
export declare function createAIReleaseBrief(packet: AIContextPacket): AIReleaseBrief;
|
|
139
|
+
export declare function renderAIReleaseBriefMarkdown(brief: AIReleaseBrief): string;
|
|
140
|
+
export declare function createAIIncidentBrief(packet: AIContextPacket): AIIncidentBrief;
|
|
141
|
+
export declare function renderAIIncidentBriefMarkdown(brief: AIIncidentBrief): string;
|
|
142
|
+
export declare function createAIDeploySummary(packet: AIContextPacket): AIDeploySummary;
|
|
143
|
+
export declare function renderAIDeploySummaryMarkdown(summary: AIDeploySummary): string;
|
|
144
|
+
export declare function createAIIncidentSnapshot(packet: AIContextPacket): AIIncidentSnapshot;
|
|
145
|
+
export declare function renderAIIncidentSnapshotMarkdown(snapshot: AIIncidentSnapshot): string;
|
package/dist-pkg/ai/summary.js
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
|
|
2
2
|
export function createAIContextPacket(report, events, latestDiagnostic, reactiveTrace) {
|
|
3
|
+
const readiness = report.readiness ?? {
|
|
4
|
+
deploy: { status: "ready", reasons: [] },
|
|
5
|
+
scaling: { status: "not-applicable", reasons: [] }
|
|
6
|
+
};
|
|
3
7
|
return {
|
|
4
8
|
schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
|
|
5
9
|
generatedAt: new Date().toISOString(),
|
|
10
|
+
app: report.app,
|
|
6
11
|
summary: {
|
|
7
12
|
headline: buildHeadline(report),
|
|
8
13
|
events: report.events.total,
|
|
9
14
|
errors: report.diagnostics.errors,
|
|
10
15
|
warnings: report.diagnostics.warnings
|
|
11
16
|
},
|
|
17
|
+
readiness,
|
|
18
|
+
release: report.release ? {
|
|
19
|
+
appMode: report.release.appMode,
|
|
20
|
+
runtimeKind: report.release.runtimeKind,
|
|
21
|
+
processEntrypoints: report.release.processEntrypoints,
|
|
22
|
+
handlerEntrypoints: report.release.handlerEntrypoints,
|
|
23
|
+
workerEntrypoint: report.release.workerEntrypoint,
|
|
24
|
+
routeCount: report.release.summary.routeCount,
|
|
25
|
+
clientAssetCount: report.release.summary.clientAssetCount,
|
|
26
|
+
prerenderedCount: report.release.summary.prerenderedCount,
|
|
27
|
+
serverEntryCount: report.release.summary.serverEntryCount,
|
|
28
|
+
generatedAt: report.release.generatedAt
|
|
29
|
+
} : void 0,
|
|
12
30
|
latestDiagnostic,
|
|
13
31
|
recentIncidents: report.incidents,
|
|
14
32
|
incidentClusters: report.incidentClusters.map((cluster) => ({
|
|
@@ -49,6 +67,13 @@ export function renderAIContextMarkdown(packet) {
|
|
|
49
67
|
"",
|
|
50
68
|
`Generated: ${packet.generatedAt}`,
|
|
51
69
|
"",
|
|
70
|
+
...packet.app ? [
|
|
71
|
+
"## App Context",
|
|
72
|
+
"",
|
|
73
|
+
`- Mode: ${packet.app.mode}`,
|
|
74
|
+
`- Runtime topology: ${packet.app.runtimeTopology}`,
|
|
75
|
+
""
|
|
76
|
+
] : [],
|
|
52
77
|
"## Summary",
|
|
53
78
|
"",
|
|
54
79
|
`- ${packet.summary.headline}`,
|
|
@@ -58,6 +83,28 @@ export function renderAIContextMarkdown(packet) {
|
|
|
58
83
|
];
|
|
59
84
|
if (packet.latestDiagnostic?.code)
|
|
60
85
|
lines.push("", "## Latest Diagnostic", "", `- ${packet.latestDiagnostic.code}: ${packet.latestDiagnostic.message ?? ""}`.trim());
|
|
86
|
+
if (packet.release) {
|
|
87
|
+
lines.push("", "## Release Artifact", "");
|
|
88
|
+
lines.push(`- Mode: ${packet.release.appMode}`);
|
|
89
|
+
lines.push(`- Runtime: ${packet.release.runtimeKind}`);
|
|
90
|
+
lines.push(`- Routes: ${packet.release.routeCount}`);
|
|
91
|
+
lines.push(`- Client assets: ${packet.release.clientAssetCount}`);
|
|
92
|
+
lines.push(`- Prerendered pages: ${packet.release.prerenderedCount}`);
|
|
93
|
+
lines.push(`- Server entries: ${packet.release.serverEntryCount}`);
|
|
94
|
+
if (packet.release.processEntrypoints.length > 0)
|
|
95
|
+
lines.push(`- Process entrypoints: ${packet.release.processEntrypoints.join(", ")}`);
|
|
96
|
+
if (packet.release.handlerEntrypoints.length > 0)
|
|
97
|
+
lines.push(`- Handler entrypoints: ${packet.release.handlerEntrypoints.join(", ")}`);
|
|
98
|
+
if (packet.release.workerEntrypoint)
|
|
99
|
+
lines.push(`- Worker entrypoint: ${packet.release.workerEntrypoint}`);
|
|
100
|
+
}
|
|
101
|
+
lines.push("", "## Readiness", "");
|
|
102
|
+
lines.push(`- Deploy: ${packet.readiness.deploy.status}`);
|
|
103
|
+
for (const reason of packet.readiness.deploy.reasons.slice(0, 3))
|
|
104
|
+
lines.push(` - ${reason}`);
|
|
105
|
+
lines.push(`- Scaling: ${packet.readiness.scaling.status}`);
|
|
106
|
+
for (const reason of packet.readiness.scaling.reasons.slice(0, 3))
|
|
107
|
+
lines.push(` - ${reason}`);
|
|
61
108
|
if (packet.recentIncidents.length > 0) {
|
|
62
109
|
lines.push("", "## Recent Incidents", "");
|
|
63
110
|
for (const incident of packet.recentIncidents.slice(0, 10)) {
|
|
@@ -101,11 +148,264 @@ export function renderAIContextMarkdown(packet) {
|
|
|
101
148
|
return lines.join(`
|
|
102
149
|
`);
|
|
103
150
|
}
|
|
151
|
+
export function createAIReleaseBrief(packet) {
|
|
152
|
+
const blockers = [
|
|
153
|
+
...packet.readiness.deploy.status === "blocked" ? packet.readiness.deploy.reasons : [],
|
|
154
|
+
...packet.readiness.scaling.status === "blocked" ? packet.readiness.scaling.reasons : []
|
|
155
|
+
], cautions = [
|
|
156
|
+
...packet.readiness.deploy.status === "caution" ? packet.readiness.deploy.reasons : [],
|
|
157
|
+
...packet.readiness.scaling.status === "caution" ? packet.readiness.scaling.reasons : []
|
|
158
|
+
], verdict = blockers.length > 0 ? "hold" : cautions.length > 0 ? "review" : "ship";
|
|
159
|
+
return {
|
|
160
|
+
schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
|
|
161
|
+
generatedAt: new Date().toISOString(),
|
|
162
|
+
app: packet.app,
|
|
163
|
+
release: packet.release,
|
|
164
|
+
readiness: packet.readiness,
|
|
165
|
+
verdict,
|
|
166
|
+
headline: verdict === "hold" ? "Release should not be promoted yet." : verdict === "review" ? "Release is close, but needs operator review." : "Release looks ready for promotion.",
|
|
167
|
+
blockers,
|
|
168
|
+
cautions,
|
|
169
|
+
recommendations: packet.recommendations
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export function renderAIReleaseBriefMarkdown(brief) {
|
|
173
|
+
const lines = [
|
|
174
|
+
"# Gorsee AI Release Brief",
|
|
175
|
+
"",
|
|
176
|
+
`Schema: ${brief.schemaVersion}`,
|
|
177
|
+
"",
|
|
178
|
+
`Generated: ${brief.generatedAt}`,
|
|
179
|
+
"",
|
|
180
|
+
`Verdict: ${brief.verdict}`,
|
|
181
|
+
"",
|
|
182
|
+
brief.headline
|
|
183
|
+
];
|
|
184
|
+
if (brief.release) {
|
|
185
|
+
lines.push("", "## Release", "");
|
|
186
|
+
lines.push(`- Mode: ${brief.release.appMode}`);
|
|
187
|
+
lines.push(`- Runtime: ${brief.release.runtimeKind}`);
|
|
188
|
+
lines.push(`- Routes: ${brief.release.routeCount}`);
|
|
189
|
+
lines.push(`- Client assets: ${brief.release.clientAssetCount}`);
|
|
190
|
+
lines.push(`- Server entries: ${brief.release.serverEntryCount}`);
|
|
191
|
+
}
|
|
192
|
+
lines.push("", "## Readiness", "");
|
|
193
|
+
lines.push(`- Deploy: ${brief.readiness.deploy.status}`);
|
|
194
|
+
lines.push(`- Scaling: ${brief.readiness.scaling.status}`);
|
|
195
|
+
if (brief.blockers.length > 0) {
|
|
196
|
+
lines.push("", "## Blockers", "");
|
|
197
|
+
for (const blocker of brief.blockers)
|
|
198
|
+
lines.push(`- ${blocker}`);
|
|
199
|
+
}
|
|
200
|
+
if (brief.cautions.length > 0) {
|
|
201
|
+
lines.push("", "## Cautions", "");
|
|
202
|
+
for (const caution of brief.cautions)
|
|
203
|
+
lines.push(`- ${caution}`);
|
|
204
|
+
}
|
|
205
|
+
if (brief.recommendations.length > 0) {
|
|
206
|
+
lines.push("", "## Recommendations", "");
|
|
207
|
+
for (const recommendation of brief.recommendations.slice(0, 5))
|
|
208
|
+
lines.push(`- ${recommendation}`);
|
|
209
|
+
}
|
|
210
|
+
return lines.join(`
|
|
211
|
+
`);
|
|
212
|
+
}
|
|
213
|
+
export function createAIIncidentBrief(packet) {
|
|
214
|
+
const severity = packet.summary.errors > 0 ? packet.incidentClusters.length > 0 && packet.incidentClusters[0].count > 1 ? "critical" : "high" : packet.summary.warnings > 0 ? "medium" : "low";
|
|
215
|
+
return {
|
|
216
|
+
schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
|
|
217
|
+
generatedAt: new Date().toISOString(),
|
|
218
|
+
app: packet.app,
|
|
219
|
+
release: packet.release,
|
|
220
|
+
readiness: packet.readiness,
|
|
221
|
+
severity,
|
|
222
|
+
headline: packet.recentIncidents[0]?.message ?? packet.summary.headline,
|
|
223
|
+
incidents: packet.recentIncidents,
|
|
224
|
+
clusters: packet.incidentClusters,
|
|
225
|
+
artifactRegressions: packet.artifactRegressions,
|
|
226
|
+
recommendations: packet.recommendations
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
export function renderAIIncidentBriefMarkdown(brief) {
|
|
230
|
+
const lines = [
|
|
231
|
+
"# Gorsee AI Incident Brief",
|
|
232
|
+
"",
|
|
233
|
+
`Schema: ${brief.schemaVersion}`,
|
|
234
|
+
"",
|
|
235
|
+
`Generated: ${brief.generatedAt}`,
|
|
236
|
+
"",
|
|
237
|
+
`Severity: ${brief.severity}`,
|
|
238
|
+
"",
|
|
239
|
+
brief.headline
|
|
240
|
+
];
|
|
241
|
+
if (brief.release) {
|
|
242
|
+
lines.push("", "## Release Context", "");
|
|
243
|
+
lines.push(`- Mode: ${brief.release.appMode}`);
|
|
244
|
+
lines.push(`- Runtime: ${brief.release.runtimeKind}`);
|
|
245
|
+
}
|
|
246
|
+
if (brief.incidents.length > 0) {
|
|
247
|
+
lines.push("", "## Incidents", "");
|
|
248
|
+
for (const incident of brief.incidents.slice(0, 5)) {
|
|
249
|
+
const loc = incident.file ? ` (${incident.file}${incident.line ? `:${incident.line}` : ""})` : incident.route ? ` (${incident.route})` : "";
|
|
250
|
+
lines.push(`- [${incident.kind}] ${incident.message}${loc}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (brief.clusters.length > 0) {
|
|
254
|
+
lines.push("", "## Clusters", "");
|
|
255
|
+
for (const cluster of brief.clusters.slice(0, 5))
|
|
256
|
+
lines.push(`- ${cluster.kind} \xD7 ${cluster.count}`);
|
|
257
|
+
}
|
|
258
|
+
if (brief.recommendations.length > 0) {
|
|
259
|
+
lines.push("", "## Recommendations", "");
|
|
260
|
+
for (const recommendation of brief.recommendations.slice(0, 5))
|
|
261
|
+
lines.push(`- ${recommendation}`);
|
|
262
|
+
}
|
|
263
|
+
return lines.join(`
|
|
264
|
+
`);
|
|
265
|
+
}
|
|
266
|
+
export function createAIDeploySummary(packet) {
|
|
267
|
+
const status = packet.readiness.deploy.status === "blocked" ? "blocked" : packet.readiness.deploy.status === "caution" || packet.readiness.scaling.status === "caution" || packet.readiness.scaling.status === "blocked" ? "review" : "ready";
|
|
268
|
+
return {
|
|
269
|
+
schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
|
|
270
|
+
generatedAt: new Date().toISOString(),
|
|
271
|
+
app: packet.app,
|
|
272
|
+
release: packet.release,
|
|
273
|
+
readiness: packet.readiness,
|
|
274
|
+
status,
|
|
275
|
+
headline: status === "blocked" ? "Deploy promotion is currently blocked by release or diagnostics signals." : status === "review" ? "Deploy promotion needs operator review before rollout." : "Deploy promotion looks ready from the current local artifact surface.",
|
|
276
|
+
processEntrypoints: packet.release?.processEntrypoints ?? [],
|
|
277
|
+
handlerEntrypoints: packet.release?.handlerEntrypoints ?? [],
|
|
278
|
+
workerEntrypoint: packet.release?.workerEntrypoint,
|
|
279
|
+
artifactRegressions: packet.artifactRegressions,
|
|
280
|
+
recommendations: packet.recommendations
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
export function renderAIDeploySummaryMarkdown(summary) {
|
|
284
|
+
const lines = [
|
|
285
|
+
"# Gorsee AI Deploy Summary",
|
|
286
|
+
"",
|
|
287
|
+
`Schema: ${summary.schemaVersion}`,
|
|
288
|
+
"",
|
|
289
|
+
`Generated: ${summary.generatedAt}`,
|
|
290
|
+
"",
|
|
291
|
+
`Status: ${summary.status}`,
|
|
292
|
+
"",
|
|
293
|
+
summary.headline
|
|
294
|
+
];
|
|
295
|
+
if (summary.app) {
|
|
296
|
+
lines.push("", "## App Context", "");
|
|
297
|
+
lines.push(`- Mode: ${summary.app.mode}`);
|
|
298
|
+
lines.push(`- Runtime topology: ${summary.app.runtimeTopology}`);
|
|
299
|
+
}
|
|
300
|
+
if (summary.release) {
|
|
301
|
+
lines.push("", "## Release Context", "");
|
|
302
|
+
lines.push(`- Mode: ${summary.release.appMode}`);
|
|
303
|
+
lines.push(`- Runtime: ${summary.release.runtimeKind}`);
|
|
304
|
+
lines.push(`- Routes: ${summary.release.routeCount}`);
|
|
305
|
+
lines.push(`- Client assets: ${summary.release.clientAssetCount}`);
|
|
306
|
+
lines.push(`- Prerendered pages: ${summary.release.prerenderedCount}`);
|
|
307
|
+
lines.push(`- Server entries: ${summary.release.serverEntryCount}`);
|
|
308
|
+
}
|
|
309
|
+
lines.push("", "## Entrypoints", "");
|
|
310
|
+
lines.push(`- Process: ${summary.processEntrypoints.length > 0 ? summary.processEntrypoints.join(", ") : "none"}`);
|
|
311
|
+
lines.push(`- Handlers: ${summary.handlerEntrypoints.length > 0 ? summary.handlerEntrypoints.join(", ") : "none"}`);
|
|
312
|
+
lines.push(`- Worker: ${summary.workerEntrypoint ?? "none"}`);
|
|
313
|
+
lines.push("", "## Readiness", "");
|
|
314
|
+
lines.push(`- Deploy: ${summary.readiness.deploy.status}`);
|
|
315
|
+
lines.push(`- Scaling: ${summary.readiness.scaling.status}`);
|
|
316
|
+
if (summary.artifactRegressions.length > 0) {
|
|
317
|
+
lines.push("", "## Artifact Regressions", "");
|
|
318
|
+
for (const regression of summary.artifactRegressions.slice(0, 5)) {
|
|
319
|
+
const path = regression.path ? ` (${regression.path})` : "";
|
|
320
|
+
lines.push(`- ${regression.phase} ${regression.latestStatus}${path}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (summary.recommendations.length > 0) {
|
|
324
|
+
lines.push("", "## Recommendations", "");
|
|
325
|
+
for (const recommendation of summary.recommendations.slice(0, 5))
|
|
326
|
+
lines.push(`- ${recommendation}`);
|
|
327
|
+
}
|
|
328
|
+
return lines.join(`
|
|
329
|
+
`);
|
|
330
|
+
}
|
|
331
|
+
export function createAIIncidentSnapshot(packet) {
|
|
332
|
+
const brief = createAIIncidentBrief(packet);
|
|
333
|
+
return {
|
|
334
|
+
schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
|
|
335
|
+
generatedAt: new Date().toISOString(),
|
|
336
|
+
app: packet.app,
|
|
337
|
+
release: packet.release,
|
|
338
|
+
readiness: packet.readiness,
|
|
339
|
+
severity: brief.severity,
|
|
340
|
+
headline: brief.headline,
|
|
341
|
+
latestIncident: packet.recentIncidents[0],
|
|
342
|
+
incidentCount: packet.recentIncidents.length,
|
|
343
|
+
clusterCount: packet.incidentClusters.length,
|
|
344
|
+
clusters: packet.incidentClusters,
|
|
345
|
+
hotspots: packet.hotspots,
|
|
346
|
+
recommendations: packet.recommendations
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
export function renderAIIncidentSnapshotMarkdown(snapshot) {
|
|
350
|
+
const lines = [
|
|
351
|
+
"# Gorsee AI Incident Snapshot",
|
|
352
|
+
"",
|
|
353
|
+
`Schema: ${snapshot.schemaVersion}`,
|
|
354
|
+
"",
|
|
355
|
+
`Generated: ${snapshot.generatedAt}`,
|
|
356
|
+
"",
|
|
357
|
+
`Severity: ${snapshot.severity}`,
|
|
358
|
+
"",
|
|
359
|
+
snapshot.headline
|
|
360
|
+
];
|
|
361
|
+
if (snapshot.app) {
|
|
362
|
+
lines.push("", "## App Context", "");
|
|
363
|
+
lines.push(`- Mode: ${snapshot.app.mode}`);
|
|
364
|
+
lines.push(`- Runtime topology: ${snapshot.app.runtimeTopology}`);
|
|
365
|
+
}
|
|
366
|
+
if (snapshot.release) {
|
|
367
|
+
lines.push("", "## Release Context", "");
|
|
368
|
+
lines.push(`- Mode: ${snapshot.release.appMode}`);
|
|
369
|
+
lines.push(`- Runtime: ${snapshot.release.runtimeKind}`);
|
|
370
|
+
}
|
|
371
|
+
lines.push("", "## Incident Overview", "");
|
|
372
|
+
lines.push(`- Incidents: ${snapshot.incidentCount}`);
|
|
373
|
+
lines.push(`- Clusters: ${snapshot.clusterCount}`);
|
|
374
|
+
if (snapshot.latestIncident)
|
|
375
|
+
lines.push(`- Latest: [${snapshot.latestIncident.kind}] ${snapshot.latestIncident.message}`);
|
|
376
|
+
if (snapshot.clusters.length > 0) {
|
|
377
|
+
lines.push("", "## Clusters", "");
|
|
378
|
+
for (const cluster of snapshot.clusters.slice(0, 5))
|
|
379
|
+
lines.push(`- ${cluster.kind} \xD7 ${cluster.count}`);
|
|
380
|
+
}
|
|
381
|
+
if (snapshot.hotspots.length > 0) {
|
|
382
|
+
lines.push("", "## Hotspots", "");
|
|
383
|
+
for (const hotspot of snapshot.hotspots.slice(0, 5))
|
|
384
|
+
lines.push(`- ${hotspot.kind}: ${hotspot.key} \xD7 ${hotspot.count}`);
|
|
385
|
+
}
|
|
386
|
+
if (snapshot.recommendations.length > 0) {
|
|
387
|
+
lines.push("", "## Recommendations", "");
|
|
388
|
+
for (const recommendation of snapshot.recommendations.slice(0, 5))
|
|
389
|
+
lines.push(`- ${recommendation}`);
|
|
390
|
+
}
|
|
391
|
+
return lines.join(`
|
|
392
|
+
`);
|
|
393
|
+
}
|
|
104
394
|
function buildHeadline(report) {
|
|
395
|
+
const readiness = report.readiness ?? {
|
|
396
|
+
deploy: { status: "ready", reasons: [] },
|
|
397
|
+
scaling: { status: "not-applicable", reasons: [] }
|
|
398
|
+
};
|
|
105
399
|
if (report.diagnostics.errors > 0)
|
|
106
400
|
return "Project currently has AI-observed errors that need attention.";
|
|
401
|
+
if (readiness.deploy.status === "blocked")
|
|
402
|
+
return "Deploy readiness is currently blocked by release, diagnostic, or artifact signals.";
|
|
403
|
+
if (readiness.scaling.status === "blocked")
|
|
404
|
+
return "Scaling readiness is currently blocked by multi-instance or distributed-state signals.";
|
|
107
405
|
if (report.diagnostics.warnings > 0)
|
|
108
406
|
return "Project is stable but has warnings worth reviewing.";
|
|
407
|
+
if (report.release)
|
|
408
|
+
return `Release artifact is present for ${report.release.appMode} (${report.release.runtimeKind}).`;
|
|
109
409
|
if (report.events.total === 0)
|
|
110
410
|
return "AI observability is enabled but no events were collected yet.";
|
|
111
411
|
return "Project looks healthy from the current AI event stream.";
|
|
@@ -129,7 +429,10 @@ function topEntries(source, kind) {
|
|
|
129
429
|
return [...source.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(([key, count]) => ({ key, count, kind }));
|
|
130
430
|
}
|
|
131
431
|
function buildRecommendations(report, latestDiagnostic, events, reactiveTrace) {
|
|
132
|
-
const recommendations = [],
|
|
432
|
+
const recommendations = [], readiness = report.readiness ?? {
|
|
433
|
+
deploy: { status: "ready", reasons: [] },
|
|
434
|
+
scaling: { status: "not-applicable", reasons: [] }
|
|
435
|
+
}, errorEvents = events.filter((event) => event.severity === "error"), requestErrors = events.filter((event) => event.kind === "request.error");
|
|
133
436
|
if (latestDiagnostic?.code)
|
|
134
437
|
recommendations.push(`Investigate the latest diagnostic ${latestDiagnostic.code} before relying on this context in automation.`);
|
|
135
438
|
if (requestErrors.length > 0)
|
|
@@ -140,6 +443,12 @@ function buildRecommendations(report, latestDiagnostic, events, reactiveTrace) {
|
|
|
140
443
|
recommendations.push("Run `gorsee ai doctor` after the next build to verify whether build-phase errors persist.");
|
|
141
444
|
if (report.artifactRegressions.length > 0)
|
|
142
445
|
recommendations.push("Review artifact regressions before shipping; release/deploy/build artifacts have recorded failures or warnings.");
|
|
446
|
+
if (report.release)
|
|
447
|
+
recommendations.push(`Validate dist/release.json before promotion; current runtime kind is ${report.release.runtimeKind}.`);
|
|
448
|
+
if (readiness.deploy.status !== "ready")
|
|
449
|
+
recommendations.push(`Deploy readiness is ${readiness.deploy.status}; resolve the reported release/artifact issues before promotion.`);
|
|
450
|
+
if (readiness.scaling.status === "blocked" || readiness.scaling.status === "caution")
|
|
451
|
+
recommendations.push(`Scaling readiness is ${readiness.scaling.status}; review runtime.topology and distributed-state signals before horizontal rollout.`);
|
|
143
452
|
if (reactiveTrace && reactiveTrace.events.length > 0)
|
|
144
453
|
recommendations.push("Reactive trace data is available; inspect dependency edges and invalidation events before changing resource or mutation behavior.");
|
|
145
454
|
if (recommendations.length === 0)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { Route } from "../router/scanner.js";
|
|
2
|
-
import { type BuildManifest } from "../server/manifest.js";
|
|
3
|
-
|
|
2
|
+
import { type BuildManifest, type ReleaseArtifact } from "../server/manifest.js";
|
|
3
|
+
import type { AppMode } from "../runtime/app-config.js";
|
|
4
|
+
export declare function createBuildManifest(routes: Route[], entryMap: Map<string, string>, hashMap: Map<string, string>, prerenderedPaths?: Iterable<string>, appMode?: AppMode): Promise<BuildManifest>;
|
|
5
|
+
export declare function createReleaseArtifact(manifest: BuildManifest, clientAssets: Iterable<string>, serverEntries: Iterable<string>): ReleaseArtifact;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { inspectRouteBuildMetadata } from "./route-metadata.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
BUILD_MANIFEST_SCHEMA_VERSION,
|
|
4
|
+
RELEASE_ARTIFACT_SCHEMA_VERSION
|
|
5
|
+
} from "../server/manifest.js";
|
|
6
|
+
export async function createBuildManifest(routes, entryMap, hashMap, prerenderedPaths = [], appMode = "fullstack") {
|
|
4
7
|
const prerendered = new Set(prerenderedPaths), manifest = {
|
|
5
8
|
schemaVersion: BUILD_MANIFEST_SCHEMA_VERSION,
|
|
9
|
+
appMode,
|
|
6
10
|
routes: {},
|
|
7
11
|
chunks: [],
|
|
8
12
|
prerendered: [...prerendered],
|
|
@@ -21,3 +25,29 @@ export async function createBuildManifest(routes, entryMap, hashMap, prerendered
|
|
|
21
25
|
manifest.chunks.push(hashed);
|
|
22
26
|
return manifest;
|
|
23
27
|
}
|
|
28
|
+
export function createReleaseArtifact(manifest, clientAssets, serverEntries) {
|
|
29
|
+
const clientAssetList = [...clientAssets].sort(), serverEntryList = [...serverEntries].sort(), prerenderedHtml = manifest.prerendered.map((pathname) => pathname === "/" ? "static/index.html" : `static/${pathname.slice(1)}/index.html`).sort(), processEntrypoints = serverEntryList.filter((entry) => entry === "prod.js" || entry === "prod-node.js"), handlerEntrypoints = serverEntryList.filter((entry) => entry === "server-handler.js" || entry === "server-handler-node.js"), workerEntrypoint = serverEntryList.includes("worker.js") ? "worker.js" : void 0;
|
|
30
|
+
return {
|
|
31
|
+
schemaVersion: RELEASE_ARTIFACT_SCHEMA_VERSION,
|
|
32
|
+
appMode: manifest.appMode ?? "fullstack",
|
|
33
|
+
generatedAt: manifest.buildTime,
|
|
34
|
+
summary: {
|
|
35
|
+
routeCount: Object.keys(manifest.routes).length,
|
|
36
|
+
clientAssetCount: clientAssetList.length,
|
|
37
|
+
prerenderedCount: manifest.prerendered.length,
|
|
38
|
+
serverEntryCount: serverEntryList.length
|
|
39
|
+
},
|
|
40
|
+
runtime: {
|
|
41
|
+
kind: manifest.appMode === "frontend" ? "frontend-static" : manifest.appMode === "server" ? "server-runtime" : "fullstack-runtime",
|
|
42
|
+
processEntrypoints,
|
|
43
|
+
handlerEntrypoints,
|
|
44
|
+
workerEntrypoint
|
|
45
|
+
},
|
|
46
|
+
artifacts: {
|
|
47
|
+
buildManifest: "manifest.json",
|
|
48
|
+
clientAssets: clientAssetList,
|
|
49
|
+
serverEntries: serverEntryList,
|
|
50
|
+
prerenderedHtml
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
package/dist-pkg/cli/cmd-ai.js
CHANGED
|
@@ -7,14 +7,18 @@ import {
|
|
|
7
7
|
createIDEProjectionWatcher,
|
|
8
8
|
createAIBridgeServer,
|
|
9
9
|
createAIContextPacket,
|
|
10
|
+
createAIIncidentBrief,
|
|
11
|
+
createAIReleaseBrief,
|
|
10
12
|
createAIMCPServer,
|
|
11
13
|
createLineReader,
|
|
12
14
|
readAIDiagnosticsSnapshot,
|
|
13
15
|
readAIEvents,
|
|
14
16
|
readReactiveTraceArtifact,
|
|
17
|
+
renderAIIncidentBriefMarkdown,
|
|
15
18
|
renderAIContextMarkdown,
|
|
16
19
|
renderAIContextBundleMarkdown,
|
|
17
20
|
renderAIFrameworkMarkdown,
|
|
21
|
+
renderAIReleaseBriefMarkdown,
|
|
18
22
|
resolveAIStorePaths,
|
|
19
23
|
resolveAISessionPackPaths,
|
|
20
24
|
resolveIDEProjectionPaths,
|
|
@@ -97,8 +101,22 @@ async function runAIDoctor(paths, flags) {
|
|
|
97
101
|
console.log(` Diagnostics: ${report.diagnostics.total}`);
|
|
98
102
|
console.log(` Errors: ${report.diagnostics.errors}`);
|
|
99
103
|
console.log(` Warnings: ${report.diagnostics.warnings}`);
|
|
104
|
+
console.log(` Deploy readiness: ${report.readiness.deploy.status}`);
|
|
105
|
+
console.log(` Scaling readiness: ${report.readiness.scaling.status}`);
|
|
100
106
|
if (report.events.latest)
|
|
101
107
|
console.log(` Latest event: ${report.events.latest.kind} @ ${report.events.latest.ts}`);
|
|
108
|
+
if (report.release) {
|
|
109
|
+
console.log(`
|
|
110
|
+
Release artifact:`);
|
|
111
|
+
console.log(` - mode=${report.release.appMode} runtime=${report.release.runtimeKind}`);
|
|
112
|
+
console.log(` - routes=${report.release.summary.routeCount} clientAssets=${report.release.summary.clientAssetCount} prerendered=${report.release.summary.prerenderedCount} serverEntries=${report.release.summary.serverEntryCount}`);
|
|
113
|
+
if (report.release.processEntrypoints.length > 0)
|
|
114
|
+
console.log(` - process=${report.release.processEntrypoints.join(", ")}`);
|
|
115
|
+
if (report.release.handlerEntrypoints.length > 0)
|
|
116
|
+
console.log(` - handlers=${report.release.handlerEntrypoints.join(", ")}`);
|
|
117
|
+
if (report.release.workerEntrypoint)
|
|
118
|
+
console.log(` - worker=${report.release.workerEntrypoint}`);
|
|
119
|
+
}
|
|
102
120
|
if (report.diagnostics.latest?.code)
|
|
103
121
|
console.log(` Latest diagnostic: ${report.diagnostics.latest.code} ${report.diagnostics.latest.message ?? ""}`.trim());
|
|
104
122
|
if (report.incidents.length > 0) {
|
|
@@ -125,6 +143,14 @@ async function runAIDoctor(paths, flags) {
|
|
|
125
143
|
console.log(` - [${artifact.phase}] errors=${artifact.errors} warnings=${artifact.warnings} successes=${artifact.successes}${details ? ` (${details})` : ""}`);
|
|
126
144
|
}
|
|
127
145
|
}
|
|
146
|
+
if (report.readiness.deploy.reasons.length > 0 || report.readiness.scaling.reasons.length > 0) {
|
|
147
|
+
console.log(`
|
|
148
|
+
Readiness reasons:`);
|
|
149
|
+
for (const reason of report.readiness.deploy.reasons.slice(0, 3))
|
|
150
|
+
console.log(` - deploy: ${reason}`);
|
|
151
|
+
for (const reason of report.readiness.scaling.reasons.slice(0, 3))
|
|
152
|
+
console.log(` - scaling: ${reason}`);
|
|
153
|
+
}
|
|
128
154
|
if (reactiveTrace) {
|
|
129
155
|
console.log(`
|
|
130
156
|
Reactive trace:`);
|
|
@@ -169,6 +195,24 @@ async function runAIExport(cwd, paths, flags) {
|
|
|
169
195
|
return;
|
|
170
196
|
}
|
|
171
197
|
const events = await readAIEvents(paths.eventsPath, { limit: flags.limit ?? 200 }), diagnostics = await readAIDiagnosticsSnapshot(paths.diagnosticsPath), reactiveTrace = await readReactiveTraceArtifact(paths.reactiveTracePath), report = await buildAIHealthReport(paths, { limit: flags.limit ?? 200 }), packet = createAIContextPacket(report, events, diagnostics?.latest, reactiveTrace);
|
|
198
|
+
if (flags.brief === "release") {
|
|
199
|
+
const brief = createAIReleaseBrief(packet);
|
|
200
|
+
if ((flags.format ?? "json") === "markdown") {
|
|
201
|
+
console.log(renderAIReleaseBriefMarkdown(brief));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
console.log(JSON.stringify(brief, null, 2));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (flags.brief === "incident") {
|
|
208
|
+
const brief = createAIIncidentBrief(packet);
|
|
209
|
+
if ((flags.format ?? "json") === "markdown") {
|
|
210
|
+
console.log(renderAIIncidentBriefMarkdown(brief));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
console.log(JSON.stringify(brief, null, 2));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
172
216
|
if ((flags.format ?? "json") === "markdown") {
|
|
173
217
|
console.log(renderAIContextMarkdown(packet));
|
|
174
218
|
return;
|
|
@@ -186,6 +230,14 @@ async function runAIPack(cwd, paths, flags) {
|
|
|
186
230
|
generatedAt: result.bundle.generatedAt,
|
|
187
231
|
latestJsonPath: result.paths.latestJsonPath,
|
|
188
232
|
latestMarkdownPath: result.paths.latestMarkdownPath,
|
|
233
|
+
latestDeploySummaryJsonPath: result.paths.latestDeploySummaryJsonPath,
|
|
234
|
+
latestDeploySummaryMarkdownPath: result.paths.latestDeploySummaryMarkdownPath,
|
|
235
|
+
latestReleaseBriefJsonPath: result.paths.latestReleaseBriefJsonPath,
|
|
236
|
+
latestReleaseBriefMarkdownPath: result.paths.latestReleaseBriefMarkdownPath,
|
|
237
|
+
latestIncidentBriefJsonPath: result.paths.latestIncidentBriefJsonPath,
|
|
238
|
+
latestIncidentBriefMarkdownPath: result.paths.latestIncidentBriefMarkdownPath,
|
|
239
|
+
latestIncidentSnapshotJsonPath: result.paths.latestIncidentSnapshotJsonPath,
|
|
240
|
+
latestIncidentSnapshotMarkdownPath: result.paths.latestIncidentSnapshotMarkdownPath,
|
|
189
241
|
historyDir: result.paths.historyDir,
|
|
190
242
|
snippets: result.bundle.snippets.length
|
|
191
243
|
}, null, 2));
|
|
@@ -196,6 +248,14 @@ async function runAIPack(cwd, paths, flags) {
|
|
|
196
248
|
`);
|
|
197
249
|
console.log(` latest json -> ${result.paths.latestJsonPath}`);
|
|
198
250
|
console.log(` latest md -> ${result.paths.latestMarkdownPath}`);
|
|
251
|
+
console.log(` deploy -> ${result.paths.latestDeploySummaryJsonPath}`);
|
|
252
|
+
console.log(` deploy md -> ${result.paths.latestDeploySummaryMarkdownPath}`);
|
|
253
|
+
console.log(` release -> ${result.paths.latestReleaseBriefJsonPath}`);
|
|
254
|
+
console.log(` release md -> ${result.paths.latestReleaseBriefMarkdownPath}`);
|
|
255
|
+
console.log(` incident -> ${result.paths.latestIncidentBriefJsonPath}`);
|
|
256
|
+
console.log(` incident md -> ${result.paths.latestIncidentBriefMarkdownPath}`);
|
|
257
|
+
console.log(` snapshot -> ${result.paths.latestIncidentSnapshotJsonPath}`);
|
|
258
|
+
console.log(` snapshot md -> ${result.paths.latestIncidentSnapshotMarkdownPath}`);
|
|
199
259
|
console.log(` history -> ${result.paths.historyDir}`);
|
|
200
260
|
console.log(` snippets -> ${result.bundle.snippets.length}`);
|
|
201
261
|
console.log();
|
|
@@ -274,6 +334,11 @@ function parseAIFlags(args) {
|
|
|
274
334
|
if (format === "json" || format === "markdown")
|
|
275
335
|
flags.format = format;
|
|
276
336
|
}
|
|
337
|
+
if (arg === "--brief") {
|
|
338
|
+
const brief = args[i + 1];
|
|
339
|
+
if (brief === "release" || brief === "incident")
|
|
340
|
+
flags.brief = brief;
|
|
341
|
+
}
|
|
277
342
|
}
|
|
278
343
|
return flags;
|
|
279
344
|
}
|
|
@@ -287,6 +352,7 @@ function printAIHelp() {
|
|
|
287
352
|
console.log(" doctor Summarize diagnostics and recent incidents");
|
|
288
353
|
console.log(" replay Replay correlated AI events in timeline order");
|
|
289
354
|
console.log(" export Export a compact AI context packet or bundle");
|
|
355
|
+
console.log(" Use --brief release|incident for verdict-oriented summaries");
|
|
290
356
|
console.log(" pack Write the latest agent-ready session pack to disk");
|
|
291
357
|
console.log(" ide-sync Write IDE-friendly diagnostics/events/context files");
|
|
292
358
|
console.log(" bridge Start local HTTP bridge for IDE/agent ingestion");
|