gorsee 0.2.7 → 0.2.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.
- package/README.md +10 -2
- package/dist-pkg/ai/framework-context.d.ts +42 -0
- package/dist-pkg/ai/framework-context.js +172 -0
- package/dist-pkg/ai/index.d.ts +1 -0
- package/dist-pkg/ai/index.js +4 -0
- package/dist-pkg/cli/cmd-ai.js +13 -0
- package/dist-pkg/cli/cmd-check.js +1 -1
- package/dist-pkg/cli/cmd-create.js +1 -0
- package/dist-pkg/cli/cmd-upgrade.d.ts +18 -0
- package/dist-pkg/cli/cmd-upgrade.js +110 -47
- package/dist-pkg/cli/framework-md.js +3 -1
- package/dist-pkg/cli/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,12 @@ npm create gorsee@latest my-app
|
|
|
95
95
|
|
|
96
96
|
Open [http://localhost:3000](http://localhost:3000).
|
|
97
97
|
|
|
98
|
+
For agent cold-start context:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
bunx gorsee ai framework --format markdown
|
|
102
|
+
```
|
|
103
|
+
|
|
98
104
|
## Why Gorsee
|
|
99
105
|
|
|
100
106
|
Most modern frameworks optimize for flexibility, historical compatibility, or ecosystem breadth.
|
|
@@ -115,6 +121,7 @@ What that means in practice:
|
|
|
115
121
|
- content collections with nested frontmatter parsing, schema validation, excerpts, block-scalar support, and locale-aware querying
|
|
116
122
|
- deterministic plugin platform with capabilities, dependency ordering, config validation, and conformance testing
|
|
117
123
|
- AI diagnostics, saved reactive-trace ingestion, context bundles, IDE projections, and MCP integration built into the framework lifecycle
|
|
124
|
+
- canonical cold-start framework packets via `gorsee ai framework`
|
|
118
125
|
- CLI enforcement through `gorsee check`, release gates, deploy contracts, and policy docs
|
|
119
126
|
- machine-readable public API stability enforcement through `bun run api:policy`
|
|
120
127
|
- machine-readable adoption and market-ready proof enforcement through `bun run adoption:policy`
|
|
@@ -255,7 +262,7 @@ npm create gorsee@latest my-app
|
|
|
255
262
|
| `gorsee routes` | Show route table |
|
|
256
263
|
| `gorsee generate <entity>` | Generate CRUD scaffold with typed routes, validated forms, and inferred `memory|sqlite|postgres` data mode |
|
|
257
264
|
| `gorsee docs --format json --contracts` | Emit machine-readable route/docs contract artifact |
|
|
258
|
-
| `gorsee upgrade
|
|
265
|
+
| `gorsee upgrade` | Upgrade to the latest published Gorsee version, rewrite obvious migration drift, write `docs/upgrade-report.json`, and run verification |
|
|
259
266
|
| `gorsee typegen` | Generate typed routes |
|
|
260
267
|
| `gorsee migrate` | Run database migrations |
|
|
261
268
|
| `gorsee deploy` | Generate deploy config for supported targets, with `--runtime bun|node` on process-based adapters |
|
|
@@ -269,7 +276,8 @@ Runtime debugging surface:
|
|
|
269
276
|
Migration ergonomics:
|
|
270
277
|
|
|
271
278
|
- `gorsee check --rewrite-imports --rewrite-loaders` can normalize obvious scoped-import and `loader -> load` drift before the audit runs.
|
|
272
|
-
- `gorsee upgrade
|
|
279
|
+
- `gorsee upgrade` is the canonical end-to-end upgrade flow for installed apps.
|
|
280
|
+
- `gorsee upgrade --check --report docs/upgrade-report.json` is the dry-run migration audit flow when you want review before installation.
|
|
273
281
|
|
|
274
282
|
## Product Standards
|
|
275
283
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface AIFrameworkDocRef {
|
|
2
|
+
path: string;
|
|
3
|
+
purpose: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AIFrameworkPacket {
|
|
6
|
+
kind: "gorsee.framework";
|
|
7
|
+
schemaVersion: 1;
|
|
8
|
+
generatedAt: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
projectName: string;
|
|
11
|
+
product: {
|
|
12
|
+
name: "Gorsee";
|
|
13
|
+
version?: string;
|
|
14
|
+
identity: string;
|
|
15
|
+
maturity: string;
|
|
16
|
+
};
|
|
17
|
+
entrypoints: {
|
|
18
|
+
browser: string;
|
|
19
|
+
server: string;
|
|
20
|
+
compatibility: string;
|
|
21
|
+
scoped: string[];
|
|
22
|
+
};
|
|
23
|
+
routeGrammar: string[];
|
|
24
|
+
syntax: {
|
|
25
|
+
browserImports: string;
|
|
26
|
+
serverImports: string;
|
|
27
|
+
routeExample: string;
|
|
28
|
+
};
|
|
29
|
+
aiCommands: Array<{
|
|
30
|
+
command: string;
|
|
31
|
+
purpose: string;
|
|
32
|
+
}>;
|
|
33
|
+
docs: {
|
|
34
|
+
local: AIFrameworkDocRef[];
|
|
35
|
+
canonical: AIFrameworkDocRef[];
|
|
36
|
+
};
|
|
37
|
+
recommendedStart: string[];
|
|
38
|
+
frameworkReferencePath?: string;
|
|
39
|
+
frameworkReferenceMarkdown: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function buildAIFrameworkPacket(cwd: string): Promise<AIFrameworkPacket>;
|
|
42
|
+
export declare function renderAIFrameworkMarkdown(packet: AIFrameworkPacket): string;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import { basename, join, relative } from "node:path";
|
|
3
|
+
import { generateFrameworkMD } from "../cli/framework-md.js";
|
|
4
|
+
const LOCAL_DOCS = [
|
|
5
|
+
{ path: "AGENTS.md", purpose: "\u041F\u0440\u043E\u0435\u043A\u0442\u043D\u044B\u0439 operating contract \u0434\u043B\u044F \u0430\u0433\u0435\u043D\u0442\u043E\u0432" },
|
|
6
|
+
{ path: "FRAMEWORK.md", purpose: "AI-friendly reference \u0434\u043B\u044F \u0442\u0435\u043A\u0443\u0449\u0435\u0433\u043E \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F" },
|
|
7
|
+
{ path: "README.md", purpose: "\u0411\u044B\u0441\u0442\u0440\u044B\u0439 \u0432\u0445\u043E\u0434 \u0438 \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u0430\u044F \u043F\u043E\u0432\u0435\u0440\u0445\u043D\u043E\u0441\u0442\u044C" }
|
|
8
|
+
], CANONICAL_DOCS = [
|
|
9
|
+
{ path: "docs/FRAMEWORK_DOCTRINE.md", purpose: "\u0410\u0440\u0445\u0438\u0442\u0435\u043A\u0442\u0443\u0440\u043D\u0430\u044F \u0434\u043E\u043A\u0442\u0440\u0438\u043D\u0430 \u0438 \u0438\u043D\u0432\u0430\u0440\u0438\u0430\u043D\u0442\u044B" },
|
|
10
|
+
{ path: "docs/API_STABILITY.md", purpose: "\u0421\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u044B\u0435 \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0435 entrypoints \u0438 migration semantics" },
|
|
11
|
+
{ path: "docs/SECURITY_MODEL.md", purpose: "Runtime/security guarantees \u0438 fail-closed \u043C\u043E\u0434\u0435\u043B\u044C" },
|
|
12
|
+
{ path: "docs/AI_WORKFLOWS.md", purpose: "\u041A\u0430\u043D\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0439 human+agent workflow" },
|
|
13
|
+
{ path: "docs/AI_SURFACE_STABILITY.md", purpose: "\u0421\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C AI-facing surface" },
|
|
14
|
+
{ path: "docs/AI_SESSION_PACKS.md", purpose: "Cross-session handoff \u0434\u043B\u044F \u0430\u0433\u0435\u043D\u0442\u043E\u0432" },
|
|
15
|
+
{ path: "docs/STARTER_ONBOARDING.md", purpose: "\u0421\u0442\u0430\u0440\u0442\u043E\u0432\u044B\u0435 app-\u043A\u043B\u0430\u0441\u0441\u044B \u0438 onboarding path" },
|
|
16
|
+
{ path: "docs/MIGRATION_GUIDE.md", purpose: "\u041F\u0435\u0440\u0435\u0445\u043E\u0434 \u0441 compatibility imports \u043D\u0430 canonical surfaces" },
|
|
17
|
+
{ path: "docs/RUNTIME_TRIAGE.md", purpose: "\u0422\u0440\u0438\u0430\u0436 runtime/regression \u043F\u0440\u043E\u0431\u043B\u0435\u043C" },
|
|
18
|
+
{ path: "docs/STARTER_FAILURES.md", purpose: "\u0427\u0430\u0441\u0442\u044B\u0435 \u043E\u0448\u0438\u0431\u043A\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0438 scaffold" }
|
|
19
|
+
], AI_COMMANDS = [
|
|
20
|
+
{ command: "gorsee ai framework --format markdown", purpose: "\u041A\u0430\u043D\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0439 cold-start packet \u043F\u043E \u0444\u0440\u0435\u0439\u043C\u0432\u043E\u0440\u043A\u0443" },
|
|
21
|
+
{ command: "gorsee ai export --format markdown", purpose: "\u041A\u043E\u043C\u043F\u0430\u043A\u0442\u043D\u044B\u0439 packet \u043F\u043E \u0442\u0435\u043A\u0443\u0449\u0435\u043C\u0443 AI/runtime \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u044E" },
|
|
22
|
+
{ command: "gorsee ai export --bundle --format markdown", purpose: "Runtime packet \u0441 \u0440\u0430\u043D\u0436\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u043C\u0438 code snippets" },
|
|
23
|
+
{ command: "gorsee ai doctor", purpose: "\u0421\u0432\u043E\u0434\u043A\u0430 diagnostics/incidents/artifact regressions" },
|
|
24
|
+
{ command: "gorsee ai pack", purpose: "\u0417\u0430\u043F\u0438\u0441\u044C session pack \u0432 .gorsee/agent" },
|
|
25
|
+
{ command: "gorsee ai ide-sync", purpose: "IDE-friendly projection \u0444\u0430\u0439\u043B\u043E\u0432" },
|
|
26
|
+
{ command: "gorsee ai mcp", purpose: "stdio MCP \u0441\u0435\u0440\u0432\u0435\u0440 \u043F\u043E\u0432\u0435\u0440\u0445 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0433\u043E AI state" }
|
|
27
|
+
];
|
|
28
|
+
async function pathExists(path) {
|
|
29
|
+
try {
|
|
30
|
+
await access(path);
|
|
31
|
+
return !0;
|
|
32
|
+
} catch {
|
|
33
|
+
return !1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function readJSON(path) {
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(await readFile(path, "utf-8"));
|
|
39
|
+
} catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function resolveFrameworkVersion() {
|
|
44
|
+
for (const candidate of [
|
|
45
|
+
join(import.meta.dir, "..", "..", "package.json"),
|
|
46
|
+
join(import.meta.dir, "..", "package.json")
|
|
47
|
+
]) {
|
|
48
|
+
const pkg = await readJSON(candidate);
|
|
49
|
+
if (typeof pkg?.version === "string")
|
|
50
|
+
return pkg.version;
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
async function resolveProjectName(cwd) {
|
|
55
|
+
const pkg = await readJSON(join(cwd, "package.json"));
|
|
56
|
+
if (typeof pkg?.name === "string" && pkg.name.trim().length > 0)
|
|
57
|
+
return pkg.name;
|
|
58
|
+
return basename(cwd);
|
|
59
|
+
}
|
|
60
|
+
async function collectDocRefs(cwd, refs) {
|
|
61
|
+
const result = [];
|
|
62
|
+
for (const ref of refs)
|
|
63
|
+
if (await pathExists(join(cwd, ref.path)))
|
|
64
|
+
result.push(ref);
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function renderDocLines(docs) {
|
|
68
|
+
return docs.map((doc) => `- \`${doc.path}\` -- ${doc.purpose}`);
|
|
69
|
+
}
|
|
70
|
+
export async function buildAIFrameworkPacket(cwd) {
|
|
71
|
+
const projectName = await resolveProjectName(cwd), localDocs = await collectDocRefs(cwd, LOCAL_DOCS), canonicalDocs = await collectDocRefs(cwd, CANONICAL_DOCS), frameworkReferencePath = await pathExists(join(cwd, "FRAMEWORK.md")) ? relative(cwd, join(cwd, "FRAMEWORK.md")) || "FRAMEWORK.md" : void 0, frameworkReferenceMarkdown = frameworkReferencePath ? await readFile(join(cwd, frameworkReferencePath), "utf-8") : generateFrameworkMD(projectName);
|
|
72
|
+
return {
|
|
73
|
+
kind: "gorsee.framework",
|
|
74
|
+
schemaVersion: 1,
|
|
75
|
+
generatedAt: new Date().toISOString(),
|
|
76
|
+
cwd,
|
|
77
|
+
projectName,
|
|
78
|
+
product: {
|
|
79
|
+
name: "Gorsee",
|
|
80
|
+
version: await resolveFrameworkVersion(),
|
|
81
|
+
identity: "AI-first reactive full-stack framework for deterministic human and agent collaboration",
|
|
82
|
+
maturity: "Mature product framework with strict runtime, security, release, and AI workflow contracts"
|
|
83
|
+
},
|
|
84
|
+
entrypoints: {
|
|
85
|
+
browser: "gorsee/client",
|
|
86
|
+
server: "gorsee/server",
|
|
87
|
+
compatibility: "gorsee and gorsee/compat are compatibility-only for new code",
|
|
88
|
+
scoped: ["gorsee/auth", "gorsee/db", "gorsee/security", "gorsee/log", "gorsee/forms", "gorsee/routes", "gorsee/ai"]
|
|
89
|
+
},
|
|
90
|
+
routeGrammar: [
|
|
91
|
+
"default export -> page UI",
|
|
92
|
+
"load -> route data reads",
|
|
93
|
+
"action -> page-bound mutations",
|
|
94
|
+
"cache -> declarative cache policy",
|
|
95
|
+
"middleware -> request policy and cross-cutting guards",
|
|
96
|
+
"GET/POST/etc -> raw HTTP endpoints"
|
|
97
|
+
],
|
|
98
|
+
syntax: {
|
|
99
|
+
browserImports: 'import { createSignal, Head, Link } from "gorsee/client"',
|
|
100
|
+
serverImports: 'import { middleware, type Context } from "gorsee/server"',
|
|
101
|
+
routeExample: "routes/users/[id].tsx -> /users/:id"
|
|
102
|
+
},
|
|
103
|
+
aiCommands: AI_COMMANDS,
|
|
104
|
+
docs: {
|
|
105
|
+
local: localDocs,
|
|
106
|
+
canonical: canonicalDocs
|
|
107
|
+
},
|
|
108
|
+
recommendedStart: [
|
|
109
|
+
"Read AGENTS.md first when it exists.",
|
|
110
|
+
"Read FRAMEWORK.md for the current app shape and syntax.",
|
|
111
|
+
"Use gorsee/client for browser-safe code and gorsee/server for runtime/server boundaries.",
|
|
112
|
+
"Prefer scoped stable subpaths when auth, db, security, forms, routes, ai, or log is the primary concern.",
|
|
113
|
+
"Use gorsee ai export --bundle for incident/debug context, not for framework cold-start context."
|
|
114
|
+
],
|
|
115
|
+
frameworkReferencePath,
|
|
116
|
+
frameworkReferenceMarkdown
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export function renderAIFrameworkMarkdown(packet) {
|
|
120
|
+
return [
|
|
121
|
+
"# Gorsee AI Framework Packet",
|
|
122
|
+
"",
|
|
123
|
+
`Generated: ${packet.generatedAt}`,
|
|
124
|
+
`Project: ${packet.projectName}`,
|
|
125
|
+
packet.product.version ? `Framework Version: ${packet.product.version}` : void 0,
|
|
126
|
+
"",
|
|
127
|
+
"## Product",
|
|
128
|
+
"",
|
|
129
|
+
`- ${packet.product.identity}`,
|
|
130
|
+
`- ${packet.product.maturity}`,
|
|
131
|
+
"",
|
|
132
|
+
"## Canonical Entrypoints",
|
|
133
|
+
"",
|
|
134
|
+
`- browser: \`${packet.entrypoints.browser}\``,
|
|
135
|
+
`- server: \`${packet.entrypoints.server}\``,
|
|
136
|
+
`- compatibility: ${packet.entrypoints.compatibility}`,
|
|
137
|
+
`- scoped: ${packet.entrypoints.scoped.map((entry) => `\`${entry}\``).join(", ")}`,
|
|
138
|
+
"",
|
|
139
|
+
"## Route Grammar",
|
|
140
|
+
"",
|
|
141
|
+
...packet.routeGrammar.map((entry) => `- ${entry}`),
|
|
142
|
+
"",
|
|
143
|
+
"## Syntax",
|
|
144
|
+
"",
|
|
145
|
+
`- ${packet.syntax.browserImports}`,
|
|
146
|
+
`- ${packet.syntax.serverImports}`,
|
|
147
|
+
`- ${packet.syntax.routeExample}`,
|
|
148
|
+
"",
|
|
149
|
+
"## Recommended Start",
|
|
150
|
+
"",
|
|
151
|
+
...packet.recommendedStart.map((entry) => `- ${entry}`),
|
|
152
|
+
"",
|
|
153
|
+
"## AI Commands",
|
|
154
|
+
"",
|
|
155
|
+
...packet.aiCommands.map((entry) => `- \`${entry.command}\` -- ${entry.purpose}`),
|
|
156
|
+
"",
|
|
157
|
+
"## Local Docs",
|
|
158
|
+
"",
|
|
159
|
+
...packet.docs.local.length > 0 ? renderDocLines(packet.docs.local) : ["- No local AI/context docs detected in the current cwd."],
|
|
160
|
+
"",
|
|
161
|
+
"## Canonical Docs",
|
|
162
|
+
"",
|
|
163
|
+
...packet.docs.canonical.length > 0 ? renderDocLines(packet.docs.canonical) : ["- Canonical repo docs are not present in the current cwd."],
|
|
164
|
+
"",
|
|
165
|
+
"## Framework Reference",
|
|
166
|
+
"",
|
|
167
|
+
packet.frameworkReferencePath ? `Source: \`${packet.frameworkReferencePath}\`` : "Source: generated built-in framework reference",
|
|
168
|
+
"",
|
|
169
|
+
packet.frameworkReferenceMarkdown
|
|
170
|
+
].filter((line) => line !== void 0).join(`
|
|
171
|
+
`);
|
|
172
|
+
}
|
package/dist-pkg/ai/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { buildAIHealthReport, readAIDiagnosticsSnapshot, readReactiveTraceArtifa
|
|
|
6
6
|
export { createAIMCPServer, createLineReader, type AIMCPServerOptions, } from "./mcp.js";
|
|
7
7
|
export { createAIContextPacket, renderAIContextMarkdown, type AIContextPacket, } from "./summary.js";
|
|
8
8
|
export { buildAIContextBundle, renderAIContextBundleMarkdown, type AIContextBundle, type AIContextSnippet, } from "./bundle.js";
|
|
9
|
+
export { buildAIFrameworkPacket, renderAIFrameworkMarkdown, type AIFrameworkDocRef, type AIFrameworkPacket, } from "./framework-context.js";
|
|
9
10
|
export { buildIDEProjection, resolveIDEProjectionPaths, writeIDEProjection, type IDEProjection, type IDEProjectionPaths, } from "./ide.js";
|
|
10
11
|
export { createIDEProjectionWatcher, type IDEProjectionWatcher, type IDEProjectionWatcherOptions, } from "./watch.js";
|
|
11
12
|
export { resolveAISessionPackConfig, resolveAISessionPackPaths, shouldGenerateAISessionPack, writeAISessionPack, type AISessionPackConfig, type AISessionPackPaths, } from "./session-pack.js";
|
package/dist-pkg/ai/index.js
CHANGED
|
@@ -37,6 +37,10 @@ export {
|
|
|
37
37
|
buildAIContextBundle,
|
|
38
38
|
renderAIContextBundleMarkdown
|
|
39
39
|
} from "./bundle.js";
|
|
40
|
+
export {
|
|
41
|
+
buildAIFrameworkPacket,
|
|
42
|
+
renderAIFrameworkMarkdown
|
|
43
|
+
} from "./framework-context.js";
|
|
40
44
|
export {
|
|
41
45
|
buildIDEProjection,
|
|
42
46
|
resolveIDEProjectionPaths,
|
package/dist-pkg/cli/cmd-ai.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createProjectContext } from "../runtime/project.js";
|
|
|
2
2
|
import {
|
|
3
3
|
buildAIHealthReport,
|
|
4
4
|
buildAIContextBundle,
|
|
5
|
+
buildAIFrameworkPacket,
|
|
5
6
|
buildIDEProjection,
|
|
6
7
|
createIDEProjectionWatcher,
|
|
7
8
|
createAIBridgeServer,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
readReactiveTraceArtifact,
|
|
14
15
|
renderAIContextMarkdown,
|
|
15
16
|
renderAIContextBundleMarkdown,
|
|
17
|
+
renderAIFrameworkMarkdown,
|
|
16
18
|
resolveAIStorePaths,
|
|
17
19
|
resolveAISessionPackPaths,
|
|
18
20
|
resolveIDEProjectionPaths,
|
|
@@ -22,6 +24,8 @@ import {
|
|
|
22
24
|
export async function runAI(args, options = {}) {
|
|
23
25
|
const subcommand = args[0] ?? "help", flags = parseAIFlags(args.slice(1)), { cwd } = createProjectContext(options), paths = resolveAIStorePaths(cwd);
|
|
24
26
|
switch (subcommand) {
|
|
27
|
+
case "framework":
|
|
28
|
+
return runAIFramework(cwd, flags);
|
|
25
29
|
case "tail":
|
|
26
30
|
return runAITail(paths.eventsPath, flags);
|
|
27
31
|
case "doctor":
|
|
@@ -43,6 +47,14 @@ export async function runAI(args, options = {}) {
|
|
|
43
47
|
printAIHelp();
|
|
44
48
|
}
|
|
45
49
|
}
|
|
50
|
+
async function runAIFramework(cwd, flags) {
|
|
51
|
+
const packet = await buildAIFrameworkPacket(cwd);
|
|
52
|
+
if ((flags.format ?? "json") === "markdown") {
|
|
53
|
+
console.log(renderAIFrameworkMarkdown(packet));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
console.log(JSON.stringify(packet, null, 2));
|
|
57
|
+
}
|
|
46
58
|
async function runAITail(eventsPath, flags) {
|
|
47
59
|
const events = await readAIEvents(eventsPath, { limit: flags.limit ?? 20 });
|
|
48
60
|
if (flags.json) {
|
|
@@ -270,6 +282,7 @@ function printAIHelp() {
|
|
|
270
282
|
gorsee ai <subcommand>
|
|
271
283
|
`);
|
|
272
284
|
console.log(" Subcommands:");
|
|
285
|
+
console.log(" framework Export canonical framework context for cold-start agents");
|
|
273
286
|
console.log(" tail Read recent structured AI events");
|
|
274
287
|
console.log(" doctor Summarize diagnostics and recent incidents");
|
|
275
288
|
console.log(" replay Replay correlated AI events in timeline order");
|
|
@@ -190,7 +190,7 @@ function checkImportContracts(cwd, astFacts) {
|
|
|
190
190
|
code: "W916",
|
|
191
191
|
file: rel,
|
|
192
192
|
message: 'Route module still exports "loader" instead of canonical "load"',
|
|
193
|
-
fix: 'Rename exported "loader" to "load", or run `gorsee check --rewrite-loaders` / `gorsee upgrade
|
|
193
|
+
fix: 'Rename exported "loader" to "load", or run `gorsee check --rewrite-loaders` / `gorsee upgrade` to rewrite obvious cases automatically'
|
|
194
194
|
});
|
|
195
195
|
for (const drift of collectCanonicalImportDrift(facts.imports)) {
|
|
196
196
|
const entries = [...drift.replacements.entries()].map(([name, target]) => `${name} -> ${target}`).join(", "), targets = [...new Set(drift.replacements.values())].join(", ");
|
|
@@ -472,6 +472,7 @@ Use the Gorsee docs to pick one clear path before expanding architecture.
|
|
|
472
472
|
| \`bun run build\` | Production build |
|
|
473
473
|
| \`bun run start\` | Start production server |
|
|
474
474
|
| \`bun run check\` | Type check + safety audit |
|
|
475
|
+
| \`bunx gorsee ai framework --format markdown\` | Export canonical framework context for a new agent session |
|
|
475
476
|
| \`bunx gorsee ai doctor\` | Summarize AI diagnostics and incidents |
|
|
476
477
|
| \`bunx gorsee ai tail --limit 20\` | Inspect recent structured AI events |
|
|
477
478
|
| \`bunx gorsee ai export --format markdown\` | Generate a compact AI context packet |
|
|
@@ -5,6 +5,10 @@ interface UpgradeFlags {
|
|
|
5
5
|
report: string | null;
|
|
6
6
|
rewriteImports: boolean;
|
|
7
7
|
}
|
|
8
|
+
export interface UpgradeStepResult {
|
|
9
|
+
command: string[];
|
|
10
|
+
exitCode: number;
|
|
11
|
+
}
|
|
8
12
|
export interface UpgradeIssue {
|
|
9
13
|
code: string;
|
|
10
14
|
file: string;
|
|
@@ -20,6 +24,14 @@ export interface UpgradeReport {
|
|
|
20
24
|
upgradeAvailable: boolean;
|
|
21
25
|
issues: UpgradeIssue[];
|
|
22
26
|
}
|
|
27
|
+
export interface UpgradeExecutionResult {
|
|
28
|
+
report: UpgradeReport;
|
|
29
|
+
installed: boolean;
|
|
30
|
+
installResult?: UpgradeStepResult;
|
|
31
|
+
checkResult?: UpgradeStepResult;
|
|
32
|
+
changedFiles: string[];
|
|
33
|
+
reportPath: string;
|
|
34
|
+
}
|
|
23
35
|
export declare function parseUpgradeFlags(args: string[]): UpgradeFlags;
|
|
24
36
|
/** Compare semver strings: -1 (a < b), 0 (equal), 1 (a > b) */
|
|
25
37
|
export declare function compareVersions(a: string, b: string): number;
|
|
@@ -32,6 +44,12 @@ export declare function collectUpgradeReport(cwd: string, versions: {
|
|
|
32
44
|
export declare function writeUpgradeReport(cwd: string, reportPath: string, report: UpgradeReport): Promise<void>;
|
|
33
45
|
export interface UpgradeCommandOptions extends RuntimeOptions {
|
|
34
46
|
}
|
|
47
|
+
export declare function performUpgrade(cwd: string, flags: UpgradeFlags, hooks?: {
|
|
48
|
+
fetchLatestVersion?: () => Promise<string | null>;
|
|
49
|
+
getCurrentVersion?: (cwd: string) => Promise<string | null>;
|
|
50
|
+
runInstallStep?: (cwd: string) => Promise<UpgradeStepResult>;
|
|
51
|
+
runCheckStep?: (cwd: string) => Promise<UpgradeStepResult>;
|
|
52
|
+
}): Promise<UpgradeExecutionResult | null>;
|
|
35
53
|
export declare function upgradeFramework(args: string[], options?: UpgradeCommandOptions): Promise<void>;
|
|
36
54
|
/** @deprecated Use upgradeFramework() for programmatic access. */
|
|
37
55
|
export declare function runUpgrade(args: string[], options?: UpgradeCommandOptions): Promise<void>;
|
|
@@ -39,6 +39,7 @@ async function getCurrentVersion(cwd) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
export const NPM_REGISTRY_URL = "https://registry.npmjs.org/gorsee/latest";
|
|
42
|
+
const DEFAULT_UPGRADE_REPORT_PATH = "docs/upgrade-report.json";
|
|
42
43
|
async function fetchLatestVersion() {
|
|
43
44
|
try {
|
|
44
45
|
const res = await fetch(NPM_REGISTRY_URL);
|
|
@@ -124,7 +125,7 @@ export async function collectUpgradeIssues(cwd) {
|
|
|
124
125
|
issues.push(issue(drift.source === "gorsee/server" ? "UG009" : "UG010", relative(cwd, file), `Domain APIs still come from "${drift.source}" instead of scoped stable subpaths: ${entries}`, drift.source === "gorsee/server" ? `Keep runtime primitives on "gorsee/server" and move domain imports to ${targets}` : `Keep browser runtime primitives on "gorsee/client" and move domain imports to ${targets}`, "info"));
|
|
125
126
|
}
|
|
126
127
|
if (facts.exportedNames.has("loader"))
|
|
127
|
-
issues.push(issue("UG011", relative(cwd, file), 'Route module still exports "loader" instead of canonical "load"', 'Rename exported "loader" to "load", or run `gorsee upgrade
|
|
128
|
+
issues.push(issue("UG011", relative(cwd, file), 'Route module still exports "loader" instead of canonical "load"', 'Rename exported "loader" to "load", or run `gorsee upgrade` to rewrite obvious cases automatically', "info"));
|
|
128
129
|
}
|
|
129
130
|
return issues;
|
|
130
131
|
}
|
|
@@ -145,87 +146,149 @@ export async function writeUpgradeReport(cwd, reportPath, report) {
|
|
|
145
146
|
await writeFile(outputPath, JSON.stringify(report, null, 2) + `
|
|
146
147
|
`, "utf-8");
|
|
147
148
|
}
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
async function runProcess(command, cwd) {
|
|
150
|
+
const exitCode = await Bun.spawn(command, {
|
|
151
|
+
cwd,
|
|
152
|
+
stdout: "inherit",
|
|
153
|
+
stderr: "inherit"
|
|
154
|
+
}).exited;
|
|
155
|
+
return { command, exitCode };
|
|
156
|
+
}
|
|
157
|
+
async function runInstallStep(cwd) {
|
|
158
|
+
return runProcess(["bun", "add", "gorsee@latest"], cwd);
|
|
159
|
+
}
|
|
160
|
+
async function runCheckStep(cwd) {
|
|
161
|
+
return runProcess(["bun", "run", "check"], cwd);
|
|
162
|
+
}
|
|
163
|
+
async function rewriteUpgradeDrift(cwd) {
|
|
164
|
+
const importRewrite = await rewriteCanonicalImportsInProject(cwd), loaderRewrite = await rewriteLegacyLoadersInProject(cwd);
|
|
165
|
+
return [...new Set([...importRewrite.changedFiles, ...loaderRewrite.changedFiles])].sort();
|
|
166
|
+
}
|
|
167
|
+
function printChangedFiles(changedFiles) {
|
|
168
|
+
if (changedFiles.length > 0) {
|
|
169
|
+
console.log(`
|
|
154
170
|
Rewrote canonical imports and loader aliases:`);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
console.log(`
|
|
159
|
-
Canonical import and loader rewrite found no changes.`);
|
|
171
|
+
for (const file of changedFiles)
|
|
172
|
+
console.log(` - ${file}`);
|
|
173
|
+
return;
|
|
160
174
|
}
|
|
161
|
-
|
|
175
|
+
console.log(`
|
|
176
|
+
Canonical import and loader rewrite found no changes.`);
|
|
177
|
+
}
|
|
178
|
+
export async function performUpgrade(cwd, flags, hooks = {}) {
|
|
179
|
+
const getCurrentVersionImpl = hooks.getCurrentVersion ?? getCurrentVersion, fetchLatestVersionImpl = hooks.fetchLatestVersion ?? fetchLatestVersion, runInstallStepImpl = hooks.runInstallStep ?? runInstallStep, runCheckStepImpl = hooks.runCheckStep ?? runCheckStep, reportPath = flags.report ?? DEFAULT_UPGRADE_REPORT_PATH, current = await getCurrentVersionImpl(cwd);
|
|
162
180
|
if (!current) {
|
|
163
181
|
console.log(`
|
|
164
182
|
Gorsee.js not found in node_modules. Run: bun add gorsee
|
|
165
183
|
`);
|
|
166
|
-
return;
|
|
184
|
+
return null;
|
|
167
185
|
}
|
|
168
186
|
console.log(`
|
|
169
187
|
Current version: v${current}`);
|
|
170
|
-
const latest = await
|
|
188
|
+
const latest = await fetchLatestVersionImpl();
|
|
171
189
|
if (!latest) {
|
|
172
190
|
console.log(` Could not fetch latest version from npm registry.
|
|
173
191
|
`);
|
|
174
|
-
return;
|
|
192
|
+
return null;
|
|
175
193
|
}
|
|
176
|
-
|
|
194
|
+
console.log(` Latest version: v${latest}`);
|
|
195
|
+
const preflightReport = await collectUpgradeReport(cwd, {
|
|
177
196
|
currentVersion: current,
|
|
178
197
|
latestVersion: latest
|
|
179
198
|
});
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
199
|
+
await writeUpgradeReport(cwd, reportPath, preflightReport);
|
|
200
|
+
console.log(` Upgrade report: ${reportPath}`);
|
|
201
|
+
if (preflightReport.issues.length > 0) {
|
|
202
|
+
console.log(`
|
|
203
|
+
Migration audit:`);
|
|
204
|
+
for (const entry of preflightReport.issues)
|
|
205
|
+
console.log(` - [${entry.code}] ${entry.file}: ${entry.message}`);
|
|
183
206
|
}
|
|
184
207
|
if (compareVersions(current, latest) >= 0) {
|
|
185
208
|
console.log(` Already up to date (v${current})`);
|
|
186
|
-
if (
|
|
209
|
+
if (flags.check) {
|
|
210
|
+
console.log();
|
|
211
|
+
return {
|
|
212
|
+
report: preflightReport,
|
|
213
|
+
installed: !1,
|
|
214
|
+
changedFiles: [],
|
|
215
|
+
reportPath
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const changedFiles = await rewriteUpgradeDrift(cwd);
|
|
219
|
+
printChangedFiles(changedFiles);
|
|
220
|
+
console.log(`
|
|
221
|
+
Running upgrade verification (bun run check)...`);
|
|
222
|
+
const checkResult = await runCheckStepImpl(cwd);
|
|
223
|
+
if (checkResult.exitCode !== 0) {
|
|
187
224
|
console.log(`
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
225
|
+
Post-upgrade verification failed (exit code ${checkResult.exitCode})
|
|
226
|
+
`);
|
|
227
|
+
process.exit(checkResult.exitCode);
|
|
191
228
|
}
|
|
192
|
-
console.log();
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
console.log(` Latest version: v${latest}`);
|
|
196
|
-
console.log(` Upgrade: v${current} -> v${latest}`);
|
|
197
|
-
if (report.issues.length > 0) {
|
|
198
229
|
console.log(`
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
230
|
+
Upgrade verification passed.
|
|
231
|
+
`);
|
|
232
|
+
return {
|
|
233
|
+
report: preflightReport,
|
|
234
|
+
installed: !1,
|
|
235
|
+
checkResult,
|
|
236
|
+
changedFiles,
|
|
237
|
+
reportPath
|
|
238
|
+
};
|
|
202
239
|
}
|
|
240
|
+
console.log(` Upgrade: v${current} -> v${latest}`);
|
|
203
241
|
if (flags.check) {
|
|
204
242
|
console.log();
|
|
205
|
-
return
|
|
243
|
+
return {
|
|
244
|
+
report: preflightReport,
|
|
245
|
+
installed: !1,
|
|
246
|
+
changedFiles: [],
|
|
247
|
+
reportPath
|
|
248
|
+
};
|
|
206
249
|
}
|
|
207
|
-
|
|
250
|
+
console.log(`
|
|
251
|
+
Installing gorsee@latest...`);
|
|
252
|
+
const installResult = await runInstallStepImpl(cwd);
|
|
253
|
+
if (installResult.exitCode !== 0) {
|
|
208
254
|
console.log(`
|
|
209
|
-
|
|
255
|
+
Install failed (exit code ${installResult.exitCode})
|
|
210
256
|
`);
|
|
211
|
-
|
|
257
|
+
process.exit(installResult.exitCode);
|
|
212
258
|
}
|
|
259
|
+
const changedFiles = await rewriteUpgradeDrift(cwd);
|
|
260
|
+
printChangedFiles(changedFiles);
|
|
213
261
|
console.log(`
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
stdout: "inherit",
|
|
218
|
-
stderr: "inherit"
|
|
219
|
-
}).exited;
|
|
220
|
-
if (exitCode !== 0) {
|
|
262
|
+
Running upgrade verification (bun run check)...`);
|
|
263
|
+
const checkResult = await runCheckStepImpl(cwd);
|
|
264
|
+
if (checkResult.exitCode !== 0) {
|
|
221
265
|
console.log(`
|
|
222
|
-
|
|
266
|
+
Upgrade verification failed (exit code ${checkResult.exitCode})
|
|
223
267
|
`);
|
|
224
|
-
process.exit(exitCode);
|
|
268
|
+
process.exit(checkResult.exitCode);
|
|
225
269
|
}
|
|
270
|
+
const installedVersion = await getCurrentVersionImpl(cwd), finalReport = await collectUpgradeReport(cwd, {
|
|
271
|
+
currentVersion: installedVersion,
|
|
272
|
+
latestVersion: latest
|
|
273
|
+
});
|
|
274
|
+
await writeUpgradeReport(cwd, reportPath, finalReport);
|
|
226
275
|
console.log(`
|
|
227
|
-
Upgraded successfully to v${latest}
|
|
276
|
+
Upgraded successfully to v${installedVersion ?? latest}
|
|
228
277
|
`);
|
|
278
|
+
return {
|
|
279
|
+
report: finalReport,
|
|
280
|
+
installed: !0,
|
|
281
|
+
installResult,
|
|
282
|
+
checkResult,
|
|
283
|
+
changedFiles,
|
|
284
|
+
reportPath
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
export async function upgradeFramework(args, options = {}) {
|
|
288
|
+
const { cwd } = createProjectContext(options), flags = parseUpgradeFlags(args);
|
|
289
|
+
if (flags.force)
|
|
290
|
+
console.log("\n Note: --force is no longer required. `gorsee upgrade` installs by default unless --check is used.");
|
|
291
|
+
await performUpgrade(cwd, flags);
|
|
229
292
|
}
|
|
230
293
|
export async function runUpgrade(args, options = {}) {
|
|
231
294
|
return upgradeFramework(args, options);
|
|
@@ -357,6 +357,7 @@ gorsee build Production build
|
|
|
357
357
|
gorsee check Type + safety + structure check
|
|
358
358
|
gorsee check --rewrite-imports --rewrite-loaders
|
|
359
359
|
Normalize canonical imports and loader aliases before auditing
|
|
360
|
+
gorsee ai framework Export canonical framework context for cold-start agents
|
|
360
361
|
gorsee ai doctor Summarize AI diagnostics and incidents
|
|
361
362
|
gorsee ai replay Reconstruct recent correlated AI event timeline
|
|
362
363
|
gorsee ai export Export a compact agent-ready context packet
|
|
@@ -367,7 +368,8 @@ gorsee migrate Run database migrations
|
|
|
367
368
|
gorsee generate X Generate CRUD for entity X
|
|
368
369
|
\`\`\`
|
|
369
370
|
|
|
370
|
-
- For
|
|
371
|
+
- For installed apps, prefer \`gorsee upgrade\` for the full version bump + rewrite + verification flow.
|
|
372
|
+
- Use \`gorsee upgrade --check --report docs/upgrade-report.json\` for a dry-run audit without installation.
|
|
371
373
|
|
|
372
374
|
## Error Codes
|
|
373
375
|
|
package/dist-pkg/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const args = process.argv.slice(2), command = args[0], COMMANDS = {
|
|
|
11
11
|
deploy: "Generate deploy config (vercel/fly/cloudflare/netlify/docker)",
|
|
12
12
|
test: "Run tests (unit/integration/e2e)",
|
|
13
13
|
docs: "Generate API documentation from routes",
|
|
14
|
-
ai: "AI-first tooling: tail, doctor, bridge, mcp",
|
|
14
|
+
ai: "AI-first tooling: framework, tail, doctor, bridge, mcp",
|
|
15
15
|
upgrade: "Upgrade Gorsee.js with migration audit and canonical rewrites",
|
|
16
16
|
help: "Show this help message"
|
|
17
17
|
};
|