gorsee 0.2.14 → 0.2.15

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 CHANGED
@@ -20,6 +20,7 @@ Read the strategic docs:
20
20
  - [Application Modes](./docs/APPLICATION_MODES.md)
21
21
  - [Security Model](./docs/SECURITY_MODEL.md)
22
22
  - [Top-Tier Roadmap](./docs/TOP_TIER_ROADMAP.md)
23
+ - [Top-Tier Competition Plan](./docs/TOP_TIER_COMPETITION_PLAN.md)
23
24
  - [Canonical Language Plan](./docs/CANONICAL_LANGUAGE_PLAN.md)
24
25
  - [Canonical Recipes](./docs/CANONICAL_RECIPES.md)
25
26
  - [Canonical Examples](./examples/README.md)
@@ -47,6 +48,8 @@ Read the strategic docs:
47
48
  - [Runtime Triage](./docs/RUNTIME_TRIAGE.md)
48
49
  - [Starter Failures](./docs/STARTER_FAILURES.md)
49
50
  - [AI Workflows](./docs/AI_WORKFLOWS.md)
51
+ - [AI Artifact Contract](./docs/AI_ARTIFACT_CONTRACT.md)
52
+ - [CLI Contract](./docs/CLI_CONTRACT.json)
50
53
  - [AI IDE Sync Workflow](./docs/AI_IDE_SYNC_WORKFLOW.md)
51
54
  - [AI MCP Workflow](./docs/AI_MCP_WORKFLOW.md)
52
55
  - [AI Bridge Workflow](./docs/AI_BRIDGE_WORKFLOW.md)
@@ -314,6 +317,7 @@ npm create gorsee@latest my-app
314
317
  | `gorsee build` | Build client and server output |
315
318
  | `gorsee start` | Start production runtime |
316
319
  | `gorsee start --runtime node` | Start the built Node production runtime entry |
320
+ | `gorsee worker` | Run the canonical server-mode worker/service runtime entry |
317
321
  | `gorsee check [--rewrite-imports] [--rewrite-loaders]` | Type, structure, TSX contract, and safety audit, with optional canonical autofix |
318
322
  | `gorsee routes` | Show route table |
319
323
  | `gorsee generate <entity>` | Generate CRUD scaffold with typed routes, validated forms, and inferred `memory|sqlite|postgres` data mode |
@@ -322,7 +326,8 @@ npm create gorsee@latest my-app
322
326
  | `gorsee typegen` | Generate typed routes |
323
327
  | `gorsee migrate` | Run database migrations |
324
328
  | `gorsee deploy` | Generate deploy config for supported targets, with `--runtime bun|node` on process-based adapters |
325
- | `gorsee ai` | AI diagnostics, bridge, IDE sync, export, and MCP tooling |
329
+ | `gorsee test` | Run the framework-aware test command surface |
330
+ | `gorsee ai` | AI bootstrap, diagnostics, checkpoints, context export, bridge, IDE sync, and MCP tooling |
326
331
 
327
332
  Runtime debugging surface:
328
333
 
@@ -335,6 +340,13 @@ Migration ergonomics:
335
340
  - `gorsee upgrade` is the canonical end-to-end upgrade flow for installed apps.
336
341
  - `gorsee upgrade --check --report docs/upgrade-report.json` is the dry-run migration audit flow when you want review before installation.
337
342
 
343
+ AI bootstrap and handoff:
344
+
345
+ - `gorsee ai init` scaffolds `.gorsee/rules.md`, `GORSEE.md`, and `.gorsee/agent/checkpoints` for repositories that enable AI workflows.
346
+ - `gorsee ai checkpoint --mode inspect|propose|apply|operate` records explicit operator checkpoints for mutating and non-mutating sessions.
347
+ - `gorsee ai pack` writes the latest grounded handoff bundle to `.gorsee/agent/latest.{json,md}` plus deploy/release/incident briefs.
348
+ - `gorsee ai framework --format markdown` remains the canonical cold-start packet for agents and operators.
349
+
338
350
  ## Product Standards
339
351
 
340
352
  - Production behavior must remain deterministic across dev and prod.
@@ -1,6 +1,7 @@
1
1
  import type { AIDiagnostic, AIEvent } from "./index.js";
2
2
  import type { AIStorePaths, AIHealthReport } from "./store.js";
3
3
  import { type AIContextPacket } from "./summary.js";
4
+ import { type AIOperationMode } from "./rules.js";
4
5
  export interface AIContextSnippet {
5
6
  file: string;
6
7
  startLine: number;
@@ -43,5 +44,6 @@ export declare function buildAIContextBundle(cwd: string, paths: AIStorePaths, o
43
44
  limit?: number;
44
45
  snippetRadius?: number;
45
46
  maxSnippets?: number;
47
+ mode?: AIOperationMode;
46
48
  }): Promise<AIContextBundle>;
47
49
  export declare function renderAIContextBundleMarkdown(bundle: AIContextBundle): string;
@@ -3,8 +3,12 @@ import { join, isAbsolute } from "node:path";
3
3
  import { buildAIHealthReport, readAIDiagnosticsSnapshot, readAIEvents, readReactiveTraceArtifact } from "./store.js";
4
4
  import { createAIContextPacket, renderAIContextMarkdown } from "./summary.js";
5
5
  import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
6
+ import { resolveAIRulesFile } from "./rules.js";
6
7
  export async function buildAIContextBundle(cwd, paths, options = {}) {
7
- const events = await readAIEvents(paths.eventsPath, { limit: options.limit ?? 200 }), diagnostics = await readAIDiagnosticsSnapshot(paths.diagnosticsPath), reactiveTrace = await readReactiveTraceArtifact(paths.reactiveTracePath), report = await buildAIHealthReport(paths, { limit: options.limit ?? 200 }), packet = createAIContextPacket(report, events, diagnostics?.latest, reactiveTrace), rootCauses = buildRootCauseRanking(report, diagnostics?.latest, events), snippets = await collectSnippets(cwd, diagnostics?.latest, report, events, rootCauses, {
8
+ const events = await readAIEvents(paths.eventsPath, { limit: options.limit ?? 200 }), diagnostics = await readAIDiagnosticsSnapshot(paths.diagnosticsPath), reactiveTrace = await readReactiveTraceArtifact(paths.reactiveTracePath), report = await buildAIHealthReport(paths, { limit: options.limit ?? 200 }), rules = await resolveAIRulesFile(cwd), packet = createAIContextPacket(report, events, diagnostics?.latest, reactiveTrace, {
9
+ currentMode: options.mode ?? "inspect",
10
+ rules
11
+ }), rootCauses = buildRootCauseRanking(report, diagnostics?.latest, events), snippets = await collectSnippets(cwd, diagnostics?.latest, report, events, rootCauses, {
8
12
  snippetRadius: options.snippetRadius ?? 6,
9
13
  maxSnippets: options.maxSnippets ?? 5
10
14
  });
@@ -0,0 +1,33 @@
1
+ import { type AIContextBundle } from "./bundle.js";
2
+ import type { AIStorePaths } from "./store.js";
3
+ import { type AIOperationMode, type AITransportContract } from "./rules.js";
4
+ export interface AICheckpointMetadata {
5
+ schemaVersion: string;
6
+ createdAt: string;
7
+ name: string;
8
+ slug: string;
9
+ mode: AIOperationMode;
10
+ bundleJsonPath: string;
11
+ bundleMarkdownPath: string;
12
+ rulesPath?: string;
13
+ transport: AITransportContract;
14
+ }
15
+ export interface AICheckpointPaths {
16
+ checkpointsDir: string;
17
+ bundleJsonPath: string;
18
+ bundleMarkdownPath: string;
19
+ metadataPath: string;
20
+ latestPointerPath: string;
21
+ }
22
+ export declare function slugifyCheckpointName(input: string): string;
23
+ export declare function resolveAICheckpointPaths(cwd: string, name: string): AICheckpointPaths;
24
+ export declare function writeAICheckpoint(cwd: string, storePaths: AIStorePaths, options: {
25
+ name?: string;
26
+ mode: AIOperationMode;
27
+ limit?: number;
28
+ maxSnippets?: number;
29
+ }): Promise<{
30
+ bundle: AIContextBundle;
31
+ metadata: AICheckpointMetadata;
32
+ paths: AICheckpointPaths;
33
+ }>;
@@ -0,0 +1,50 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { buildAIContextBundle, renderAIContextBundleMarkdown } from "./bundle.js";
4
+ import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
5
+ import { resolveAISessionPackPaths } from "./session-pack.js";
6
+ import {
7
+ AI_TRANSPORT_CONTRACT,
8
+ resolveAIRulesFile
9
+ } from "./rules.js";
10
+ export function slugifyCheckpointName(input) {
11
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "checkpoint";
12
+ }
13
+ export function resolveAICheckpointPaths(cwd, name) {
14
+ const sessionPackPaths = resolveAISessionPackPaths(cwd), checkpointsDir = join(sessionPackPaths.outDir, "checkpoints"), slug = slugifyCheckpointName(name);
15
+ return {
16
+ checkpointsDir,
17
+ bundleJsonPath: join(checkpointsDir, `${slug}.json`),
18
+ bundleMarkdownPath: join(checkpointsDir, `${slug}.md`),
19
+ metadataPath: join(checkpointsDir, `${slug}.meta.json`),
20
+ latestPointerPath: join(checkpointsDir, "latest.json")
21
+ };
22
+ }
23
+ export async function writeAICheckpoint(cwd, storePaths, options) {
24
+ const createdAt = new Date().toISOString(), name = options.name?.trim().length ? options.name.trim() : createdAt.replace(/[:.]/g, "-"), paths = resolveAICheckpointPaths(cwd, name), bundle = await buildAIContextBundle(cwd, storePaths, {
25
+ limit: options.limit,
26
+ maxSnippets: options.maxSnippets
27
+ }), rules = await resolveAIRulesFile(cwd);
28
+ await mkdir(paths.checkpointsDir, { recursive: !0 });
29
+ const metadata = {
30
+ schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
31
+ createdAt,
32
+ name,
33
+ slug: slugifyCheckpointName(name),
34
+ mode: options.mode,
35
+ bundleJsonPath: paths.bundleJsonPath,
36
+ bundleMarkdownPath: paths.bundleMarkdownPath,
37
+ rulesPath: rules?.path,
38
+ transport: AI_TRANSPORT_CONTRACT
39
+ }, markdown = [
40
+ `<!-- gorsee-ai-schema: ${GORSEE_AI_CONTEXT_SCHEMA_VERSION} -->`,
41
+ `<!-- gorsee-ai-mode: ${options.mode} -->`,
42
+ renderAIContextBundleMarkdown(bundle)
43
+ ].join(`
44
+ `);
45
+ await writeFile(paths.bundleJsonPath, JSON.stringify(bundle, null, 2), "utf-8");
46
+ await writeFile(paths.bundleMarkdownPath, markdown, "utf-8");
47
+ await writeFile(paths.metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
48
+ await writeFile(paths.latestPointerPath, JSON.stringify(metadata, null, 2), "utf-8");
49
+ return { bundle, metadata, paths };
50
+ }
@@ -1,4 +1,5 @@
1
1
  import { type AppMode } from "../runtime/app-config.js";
2
+ import { type AIOperationModeDefinition, type AITransportContract } from "./rules.js";
2
3
  export interface AIFrameworkDocRef {
3
4
  path: string;
4
5
  purpose: string;
@@ -32,6 +33,12 @@ export interface AIFrameworkPacket {
32
33
  command: string;
33
34
  purpose: string;
34
35
  }>;
36
+ operationModes: AIOperationModeDefinition[];
37
+ transport: AITransportContract;
38
+ rules?: {
39
+ path: string;
40
+ content: string;
41
+ };
35
42
  docs: {
36
43
  local: AIFrameworkDocRef[];
37
44
  canonical: AIFrameworkDocRef[];
@@ -2,6 +2,11 @@ import { access, readFile } from "node:fs/promises";
2
2
  import { basename, join, relative } from "node:path";
3
3
  import { generateFrameworkMD } from "../cli/framework-md.js";
4
4
  import { loadAppConfig, resolveAppMode } from "../runtime/app-config.js";
5
+ import {
6
+ AI_OPERATION_MODES,
7
+ AI_TRANSPORT_CONTRACT,
8
+ resolveAIRulesFile
9
+ } from "./rules.js";
5
10
  const LOCAL_DOCS = [
6
11
  { 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" },
7
12
  { 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" },
@@ -10,21 +15,32 @@ const LOCAL_DOCS = [
10
15
  { 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" },
11
16
  { path: "docs/APPLICATION_MODES.md", purpose: "\u041A\u0430\u043D\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0440\u0435\u0436\u0438\u043C\u044B frontend/fullstack/server \u0438 \u0433\u0440\u0430\u043D\u0438\u0446\u044B \u043C\u0435\u0436\u0434\u0443 \u043D\u0438\u043C\u0438" },
12
17
  { 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" },
18
+ { path: "docs/PUBLIC_SURFACE_MAP.md", purpose: "\u041A\u0430\u043D\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0430\u044F import map \u0438 bounded public surfaces" },
19
+ { path: "docs/CLI_CONTRACT.json", purpose: "Machine-readable CLI command matrix \u0438 AI subcommand surface" },
13
20
  { path: "docs/SECURITY_MODEL.md", purpose: "Runtime/security guarantees \u0438 fail-closed \u043C\u043E\u0434\u0435\u043B\u044C" },
14
21
  { path: "docs/AI_WORKFLOWS.md", purpose: "\u041A\u0430\u043D\u043E\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0439 human+agent workflow" },
15
22
  { path: "docs/AI_SURFACE_STABILITY.md", purpose: "\u0421\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C AI-facing surface" },
23
+ { path: "docs/AI_ARTIFACT_CONTRACT.md", purpose: "Versioned AI artifacts, checkpoints, and handoff expectations" },
16
24
  { path: "docs/AI_SESSION_PACKS.md", purpose: "Cross-session handoff \u0434\u043B\u044F \u0430\u0433\u0435\u043D\u0442\u043E\u0432" },
25
+ { path: "docs/REACTIVE_RUNTIME.md", purpose: "\u0420\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0430\u044F \u043C\u043E\u0434\u0435\u043B\u044C, diagnostics, resources, mutations, islands" },
26
+ { path: "docs/SUPPORT_MATRIX.md", purpose: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u044B\u0435 runtime targets, CLI surfaces, and CI-validated contract" },
27
+ { path: "docs/DEPLOY_TARGET_GUIDE.md", purpose: "Mode-aware deploy target guidance \u0438 runtime profiles" },
17
28
  { 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" },
18
29
  { path: "docs/MIGRATION_GUIDE.md", purpose: "\u041F\u0435\u0440\u0435\u0445\u043E\u0434 \u0441 compatibility imports \u043D\u0430 canonical surfaces" },
19
30
  { path: "docs/RUNTIME_TRIAGE.md", purpose: "\u0422\u0440\u0438\u0430\u0436 runtime/regression \u043F\u0440\u043E\u0431\u043B\u0435\u043C" },
20
31
  { 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" }
21
32
  ], AI_COMMANDS = [
33
+ { command: "gorsee ai init", purpose: "Bootstrap local AI rules, operator guide, and checkpoint directory" },
22
34
  { 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" },
35
+ { command: "gorsee ai tail --limit 20", purpose: "\u041F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0445 structured AI events" },
36
+ { command: "gorsee ai replay", purpose: "\u0412\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u043A\u043E\u0440\u0440\u0435\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E AI/runtime event timeline" },
37
+ { command: "gorsee ai doctor", purpose: "\u0421\u0432\u043E\u0434\u043A\u0430 diagnostics/incidents/artifact regressions" },
23
38
  { 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" },
24
39
  { 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" },
25
- { command: "gorsee ai doctor", purpose: "\u0421\u0432\u043E\u0434\u043A\u0430 diagnostics/incidents/artifact regressions" },
26
40
  { command: "gorsee ai pack", purpose: "\u0417\u0430\u043F\u0438\u0441\u044C session pack \u0432 .gorsee/agent" },
41
+ { command: "gorsee ai checkpoint --mode inspect", purpose: "\u042F\u0432\u043D\u044B\u0439 checkpoint \u0442\u0435\u043A\u0443\u0449\u0435\u0433\u043E AI session state \u0441 metadata \u043F\u043E \u0440\u0435\u0436\u0438\u043C\u0443" },
27
42
  { command: "gorsee ai ide-sync", purpose: "IDE-friendly projection \u0444\u0430\u0439\u043B\u043E\u0432" },
43
+ { command: "gorsee ai bridge", purpose: "\u041B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0439 ingest bridge \u0434\u043B\u044F trusted IDE/agent tooling" },
28
44
  { 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" }
29
45
  ];
30
46
  async function pathExists(path) {
@@ -70,7 +86,7 @@ function renderDocLines(docs) {
70
86
  return docs.map((doc) => `- \`${doc.path}\` -- ${doc.purpose}`);
71
87
  }
72
88
  export async function buildAIFrameworkPacket(cwd) {
73
- const projectName = await resolveProjectName(cwd), appMode = resolveAppMode(await loadAppConfig(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);
89
+ const projectName = await resolveProjectName(cwd), appMode = resolveAppMode(await loadAppConfig(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), rules = await resolveAIRulesFile(cwd);
74
90
  return {
75
91
  kind: "gorsee.framework",
76
92
  schemaVersion: 1,
@@ -88,7 +104,19 @@ export async function buildAIFrameworkPacket(cwd) {
88
104
  browser: "gorsee/client",
89
105
  server: "gorsee/server",
90
106
  compatibility: "gorsee and gorsee/compat are compatibility-only for new code",
91
- scoped: ["gorsee/auth", "gorsee/db", "gorsee/security", "gorsee/log", "gorsee/forms", "gorsee/routes", "gorsee/ai"]
107
+ scoped: [
108
+ "gorsee/auth",
109
+ "gorsee/db",
110
+ "gorsee/security",
111
+ "gorsee/ai",
112
+ "gorsee/forms",
113
+ "gorsee/routes",
114
+ "gorsee/i18n",
115
+ "gorsee/content",
116
+ "gorsee/env",
117
+ "gorsee/log",
118
+ "gorsee/testing"
119
+ ]
92
120
  },
93
121
  routeGrammar: [
94
122
  "default export -> page UI",
@@ -104,6 +132,12 @@ export async function buildAIFrameworkPacket(cwd) {
104
132
  routeExample: "routes/users/[id].tsx -> /users/:id"
105
133
  },
106
134
  aiCommands: AI_COMMANDS,
135
+ operationModes: AI_OPERATION_MODES,
136
+ transport: AI_TRANSPORT_CONTRACT,
137
+ rules: rules ? {
138
+ path: rules.path,
139
+ content: rules.content
140
+ } : void 0,
107
141
  docs: {
108
142
  local: localDocs,
109
143
  canonical: canonicalDocs
@@ -111,9 +145,14 @@ export async function buildAIFrameworkPacket(cwd) {
111
145
  recommendedStart: [
112
146
  "Read AGENTS.md first when it exists.",
113
147
  "Read FRAMEWORK.md for the current app shape and syntax.",
148
+ "Read docs/PUBLIC_SURFACE_MAP.md for the canonical import map and scoped stable surfaces.",
149
+ "Read docs/SUPPORT_MATRIX.md when runtime, packaging, or deploy assumptions matter.",
150
+ "Prefer inspect/propose modes before apply/operate when the task is still ambiguous.",
114
151
  `Respect the current app.mode contract: ${appMode}.`,
115
152
  "Use gorsee/client for browser-safe code and gorsee/server for runtime/server boundaries.",
116
- "Prefer scoped stable subpaths when auth, db, security, forms, routes, ai, or log is the primary concern.",
153
+ "Prefer scoped stable subpaths when auth, db, security, forms, routes, ai, i18n, content, env, log, or testing is the primary concern.",
154
+ "Keep model traffic provider-direct or self-hosted; treat the AI bridge as diagnostics transport, not as the production request path.",
155
+ "Use gorsee ai init when local AI workflows are enabled but the repository has no explicit local rules scaffold yet.",
117
156
  "Use gorsee ai export --bundle for incident/debug context, not for framework cold-start context."
118
157
  ],
119
158
  frameworkReferencePath,
@@ -159,6 +198,16 @@ export function renderAIFrameworkMarkdown(packet) {
159
198
  "",
160
199
  ...packet.aiCommands.map((entry) => `- \`${entry.command}\` -- ${entry.purpose}`),
161
200
  "",
201
+ "## AI Operation Modes",
202
+ "",
203
+ ...packet.operationModes.map((entry) => `- \`${entry.mode}\` -- ${entry.purpose}`),
204
+ "",
205
+ "## AI Transport Contract",
206
+ "",
207
+ `- Model traffic: ${packet.transport.modelTraffic}`,
208
+ `- Bridge role: ${packet.transport.bridgeRole}`,
209
+ `- Production role: ${packet.transport.productionRole}`,
210
+ "",
162
211
  "## Local Docs",
163
212
  "",
164
213
  ...packet.docs.local.length > 0 ? renderDocLines(packet.docs.local) : ["- No local AI/context docs detected in the current cwd."],
@@ -171,6 +220,14 @@ export function renderAIFrameworkMarkdown(packet) {
171
220
  "",
172
221
  packet.frameworkReferencePath ? `Source: \`${packet.frameworkReferencePath}\`` : "Source: generated built-in framework reference",
173
222
  "",
223
+ ...packet.rules ? [
224
+ "## AI Rules",
225
+ "",
226
+ `Source: \`${packet.rules.path}\``,
227
+ "",
228
+ packet.rules.content,
229
+ ""
230
+ ] : [],
174
231
  packet.frameworkReferenceMarkdown
175
232
  ].filter((line) => line !== void 0).join(`
176
233
  `);
@@ -1,5 +1,6 @@
1
1
  import { type AIContextPacket } from "./summary.js";
2
2
  import { type AIStorePaths } from "./store.js";
3
+ import { type AIOperationMode } from "./rules.js";
3
4
  export interface IDEProjectionPaths {
4
5
  diagnosticsPath: string;
5
6
  eventsPath: string;
@@ -8,6 +9,7 @@ export interface IDEProjectionPaths {
8
9
  export interface IDEProjection {
9
10
  schemaVersion: string;
10
11
  updatedAt: string;
12
+ agent: AIContextPacket["agent"];
11
13
  app?: AIContextPacket["app"];
12
14
  diagnostics: Array<{
13
15
  code?: string;
@@ -34,5 +36,7 @@ export interface IDEProjection {
34
36
  export declare function resolveIDEProjectionPaths(cwd: string): IDEProjectionPaths;
35
37
  export declare function buildIDEProjection(storePaths: AIStorePaths, options?: {
36
38
  limit?: number;
39
+ cwd?: string;
40
+ mode?: AIOperationMode;
37
41
  }): Promise<IDEProjection>;
38
42
  export declare function writeIDEProjection(projectionPaths: IDEProjectionPaths, projection: IDEProjection): Promise<void>;
@@ -3,6 +3,7 @@ import { dirname, join } from "node:path";
3
3
  import { createAIContextPacket, renderAIContextMarkdown } from "./summary.js";
4
4
  import { buildAIHealthReport, readAIDiagnosticsSnapshot, readAIEvents, readReactiveTraceArtifact } from "./store.js";
5
5
  import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
6
+ import { resolveAIRulesFile } from "./rules.js";
6
7
  export function resolveIDEProjectionPaths(cwd) {
7
8
  const base = join(cwd, ".gorsee", "ide");
8
9
  return {
@@ -12,10 +13,14 @@ export function resolveIDEProjectionPaths(cwd) {
12
13
  };
13
14
  }
14
15
  export async function buildIDEProjection(storePaths, options = {}) {
15
- const events = await readAIEvents(storePaths.eventsPath, { limit: options.limit ?? 100 }), diagnosticsSnapshot = await readAIDiagnosticsSnapshot(storePaths.diagnosticsPath), reactiveTrace = await readReactiveTraceArtifact(storePaths.reactiveTracePath), report = await buildAIHealthReport(storePaths, { limit: options.limit ?? 200 }), context = createAIContextPacket(report, events, diagnosticsSnapshot?.latest, reactiveTrace);
16
+ const events = await readAIEvents(storePaths.eventsPath, { limit: options.limit ?? 100 }), diagnosticsSnapshot = await readAIDiagnosticsSnapshot(storePaths.diagnosticsPath), reactiveTrace = await readReactiveTraceArtifact(storePaths.reactiveTracePath), report = await buildAIHealthReport(storePaths, { limit: options.limit ?? 200 }), rules = options.cwd ? await resolveAIRulesFile(options.cwd) : void 0, context = createAIContextPacket(report, events, diagnosticsSnapshot?.latest, reactiveTrace, {
17
+ currentMode: options.mode ?? "inspect",
18
+ rules
19
+ });
16
20
  return {
17
21
  schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
18
22
  updatedAt: new Date().toISOString(),
23
+ agent: context.agent,
19
24
  app: context.app,
20
25
  diagnostics: diagnosticsSnapshot?.latest ? [{
21
26
  code: diagnosticsSnapshot.latest.code,
@@ -45,12 +50,14 @@ export async function writeIDEProjection(projectionPaths, projection) {
45
50
  await writeFile(projectionPaths.diagnosticsPath, JSON.stringify({
46
51
  schemaVersion: projection.schemaVersion,
47
52
  updatedAt: projection.updatedAt,
53
+ agent: projection.agent,
48
54
  app: projection.app,
49
55
  diagnostics: projection.diagnostics
50
56
  }, null, 2), "utf-8");
51
57
  await writeFile(projectionPaths.eventsPath, JSON.stringify({
52
58
  schemaVersion: projection.schemaVersion,
53
59
  updatedAt: projection.updatedAt,
60
+ agent: projection.agent,
54
61
  app: projection.app,
55
62
  events: projection.recentEvents,
56
63
  artifactRegressions: projection.artifactRegressions
@@ -1,5 +1,7 @@
1
1
  import { type AISessionPackConfig } from "./session-pack.js";
2
2
  export { GORSEE_AI_CONTEXT_SCHEMA_VERSION, } from "./contracts.js";
3
+ export { AI_OPERATION_MODES, AI_TRANSPORT_CONTRACT, renderDefaultAIRulesMarkdown, renderDefaultAIGuideMarkdown, resolveAIRulesFile, type AIOperationMode, type AIOperationModeDefinition, type AIRulesFile, type AITransportContract, } from "./rules.js";
4
+ export { resolveAICheckpointPaths, slugifyCheckpointName, writeAICheckpoint, type AICheckpointMetadata, type AICheckpointPaths, } from "./checkpoint.js";
3
5
  export { writeArtifactFailurePack, writeArtifactLifecycleEvent, writeArtifactSuccessPack, runArtifactLifecycleStep, type ArtifactLifecycleEventInput, } from "./artifact-lifecycle.js";
4
6
  export { createAIBridgeHandler, createAIBridgeServer, type AIBridgeHandler, type AIBridgeServer, type AIBridgeServerOptions, type AIBridgeSnapshot, } from "./bridge.js";
5
7
  export { buildAIHealthReport, readAIDiagnosticsSnapshot, readReactiveTraceArtifact, readAIEvents, resolveAIStorePaths, type AIHealthReport, type AIStorePaths, } from "./store.js";
@@ -8,6 +8,18 @@ import {
8
8
  export {
9
9
  GORSEE_AI_CONTEXT_SCHEMA_VERSION
10
10
  } from "./contracts.js";
11
+ export {
12
+ AI_OPERATION_MODES,
13
+ AI_TRANSPORT_CONTRACT,
14
+ renderDefaultAIRulesMarkdown,
15
+ renderDefaultAIGuideMarkdown,
16
+ resolveAIRulesFile
17
+ } from "./rules.js";
18
+ export {
19
+ resolveAICheckpointPaths,
20
+ slugifyCheckpointName,
21
+ writeAICheckpoint
22
+ } from "./checkpoint.js";
11
23
  export {
12
24
  writeArtifactFailurePack,
13
25
  writeArtifactLifecycleEvent,
@@ -0,0 +1,28 @@
1
+ import type { AppMode } from "../runtime/app-config.js";
2
+ export type AIOperationMode = "inspect" | "propose" | "apply" | "operate";
3
+ export interface AIOperationModeDefinition {
4
+ mode: AIOperationMode;
5
+ purpose: string;
6
+ mutatesFiles: boolean;
7
+ mutatesRuntime: boolean;
8
+ }
9
+ export interface AIRulesFile {
10
+ path: string;
11
+ content: string;
12
+ }
13
+ export interface AITransportContract {
14
+ modelTraffic: "provider-direct-or-self-hosted";
15
+ bridgeRole: "diagnostics-and-ingestion-only";
16
+ productionRole: "must-not-sit-on-the-runtime-request-path";
17
+ }
18
+ export declare const AI_OPERATION_MODES: AIOperationModeDefinition[];
19
+ export declare const AI_TRANSPORT_CONTRACT: AITransportContract;
20
+ export declare function renderDefaultAIRulesMarkdown(input: {
21
+ projectName: string;
22
+ appMode: AppMode;
23
+ }): string;
24
+ export declare function renderDefaultAIGuideMarkdown(input: {
25
+ projectName: string;
26
+ appMode: AppMode;
27
+ }): string;
28
+ export declare function resolveAIRulesFile(cwd: string): Promise<AIRulesFile | undefined>;
@@ -0,0 +1,118 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export const AI_OPERATION_MODES = [
4
+ {
5
+ mode: "inspect",
6
+ purpose: "Read code, diagnostics, and contracts without mutating files or runtime state.",
7
+ mutatesFiles: !1,
8
+ mutatesRuntime: !1
9
+ },
10
+ {
11
+ mode: "propose",
12
+ purpose: "Prepare change plans, patches, or remediation guidance without applying them.",
13
+ mutatesFiles: !1,
14
+ mutatesRuntime: !1
15
+ },
16
+ {
17
+ mode: "apply",
18
+ purpose: "Write code or config changes in the repository without operating long-running runtime surfaces.",
19
+ mutatesFiles: !0,
20
+ mutatesRuntime: !1
21
+ },
22
+ {
23
+ mode: "operate",
24
+ purpose: "Perform runtime-facing actions such as deploy, worker, bridge, or incident operations with explicit operator intent.",
25
+ mutatesFiles: !0,
26
+ mutatesRuntime: !0
27
+ }
28
+ ], AI_TRANSPORT_CONTRACT = {
29
+ modelTraffic: "provider-direct-or-self-hosted",
30
+ bridgeRole: "diagnostics-and-ingestion-only",
31
+ productionRole: "must-not-sit-on-the-runtime-request-path"
32
+ };
33
+ export function renderDefaultAIRulesMarkdown(input) {
34
+ return [
35
+ "# AI Rules",
36
+ "",
37
+ `Project: ${input.projectName}`,
38
+ `App Mode: ${input.appMode}`,
39
+ "",
40
+ "## Defaults",
41
+ "",
42
+ "- Start in `inspect` mode unless the task clearly requires mutation.",
43
+ "- Prefer `propose` before `apply` when requirements are still ambiguous.",
44
+ "- Use `operate` only for deploy, worker, bridge, incident, or other runtime-facing actions.",
45
+ "- Before `apply` or `operate`, write an explicit checkpoint with `gorsee ai checkpoint --mode <mode>`.",
46
+ "- Treat `gorsee/client` and `gorsee/server` boundaries as framework contracts, not convenience suggestions.",
47
+ "- Prefer scoped stable subpaths (`gorsee/auth`, `gorsee/forms`, `gorsee/routes`, etc.) when the concern is already domain-specific.",
48
+ "",
49
+ "## Safety",
50
+ "",
51
+ "- Keep model traffic provider-direct or self-hosted when integrating external models.",
52
+ "- Do not place AI bridge transport on the production request path.",
53
+ "- Prefer structured artifacts in `.gorsee/` over scraped logs.",
54
+ "- Run `gorsee check` after mutating AI workflows.",
55
+ "",
56
+ "## Local Notes",
57
+ "",
58
+ "- Record project-specific constraints here instead of repeating them in every prompt.",
59
+ "- Add product, security, deploy, or incident rules here when this repo develops stronger local requirements.",
60
+ ""
61
+ ].join(`
62
+ `);
63
+ }
64
+ export function renderDefaultAIGuideMarkdown(input) {
65
+ return [
66
+ "# Gorsee AI Local Guide",
67
+ "",
68
+ `Project: ${input.projectName}`,
69
+ `App Mode: ${input.appMode}`,
70
+ "",
71
+ "This file is the local operator-facing AI guide for the repository.",
72
+ "",
73
+ "## Canonical Files",
74
+ "",
75
+ "- `.gorsee/rules.md` is the canonical local rules file consumed by Gorsee AI workflows.",
76
+ "- `AGENTS.md` remains the primary repository contract when present.",
77
+ "- `FRAMEWORK.md` remains the app/framework reference when present.",
78
+ "",
79
+ "## Recommended Workflow",
80
+ "",
81
+ "1. Run `gorsee ai framework --format markdown` for cold-start context.",
82
+ "2. Keep the session in `inspect` or `propose` until mutation is justified.",
83
+ "3. Before `apply` or `operate`, run `gorsee ai checkpoint --mode <mode>`.",
84
+ "4. Use `gorsee ai pack` for handoff and `gorsee ai doctor` for diagnostics-first triage.",
85
+ "5. Run `gorsee check` after mutating work.",
86
+ "",
87
+ "## Local Customization",
88
+ "",
89
+ "- Extend `.gorsee/rules.md` with repo-specific constraints.",
90
+ "- Add team-specific AI operating notes here only when they are broader than per-task instructions.",
91
+ ""
92
+ ].join(`
93
+ `);
94
+ }
95
+ const RULES_CANDIDATES = [
96
+ ".gorsee/rules.md",
97
+ "GORSEE.md"
98
+ ];
99
+ async function pathExists(path) {
100
+ try {
101
+ await access(path);
102
+ return !0;
103
+ } catch {
104
+ return !1;
105
+ }
106
+ }
107
+ export async function resolveAIRulesFile(cwd) {
108
+ for (const candidate of RULES_CANDIDATES) {
109
+ const absolutePath = join(cwd, candidate);
110
+ if (!await pathExists(absolutePath))
111
+ continue;
112
+ return {
113
+ path: candidate,
114
+ content: await readFile(absolutePath, "utf-8")
115
+ };
116
+ }
117
+ return;
118
+ }
@@ -1,5 +1,6 @@
1
1
  import type { AIStorePaths } from "./store.js";
2
2
  import { type AIContextBundle } from "./bundle.js";
3
+ import type { AIOperationMode } from "./rules.js";
3
4
  export interface AISessionPackConfig {
4
5
  enabled?: boolean;
5
6
  outDir?: string;
@@ -8,6 +9,7 @@ export interface AISessionPackConfig {
8
9
  limit?: number;
9
10
  maxSnippets?: number;
10
11
  formats?: Array<"json" | "markdown">;
12
+ mode?: AIOperationMode;
11
13
  }
12
14
  export interface AISessionPackPaths {
13
15
  outDir: string;
@@ -45,7 +45,8 @@ export function resolveAISessionPackPaths(cwd, config) {
45
45
  export async function writeAISessionPack(cwd, storePaths, config) {
46
46
  const resolved = resolveAISessionPackConfig(cwd, { enabled: !0, ...config ?? {} }), paths = resolveAISessionPackPaths(cwd, resolved), bundle = await buildAIContextBundle(cwd, storePaths, {
47
47
  limit: resolved.limit,
48
- maxSnippets: resolved.maxSnippets
48
+ maxSnippets: resolved.maxSnippets,
49
+ mode: resolved.mode
49
50
  });
50
51
  await mkdir(paths.historyDir, { recursive: !0 });
51
52
  const stamp = bundle.generatedAt.replace(/[:.]/g, "-"), deploySummary = createAIDeploySummary(bundle.packet), releaseBrief = createAIReleaseBrief(bundle.packet), incidentBrief = createAIIncidentBrief(bundle.packet), incidentSnapshot = createAIIncidentSnapshot(bundle.packet), json = JSON.stringify(bundle, null, 2), markdown = [
@@ -1,9 +1,28 @@
1
1
  import type { AIDiagnostic, AIEvent } from "./index.js";
2
2
  import type { AIHealthReport } from "./store.js";
3
3
  import type { ReactiveTraceArtifact } from "../reactive/diagnostics.js";
4
+ import { type AIOperationMode, type AIRulesFile } from "./rules.js";
4
5
  export interface AIContextPacket {
5
6
  schemaVersion: string;
6
7
  generatedAt: string;
8
+ agent: {
9
+ currentMode: AIOperationMode;
10
+ availableModes: Array<{
11
+ mode: AIOperationMode;
12
+ purpose: string;
13
+ mutatesFiles: boolean;
14
+ mutatesRuntime: boolean;
15
+ }>;
16
+ transport: {
17
+ modelTraffic: string;
18
+ bridgeRole: string;
19
+ productionRole: string;
20
+ };
21
+ rules?: {
22
+ path: string;
23
+ content: string;
24
+ };
25
+ };
7
26
  app?: {
8
27
  mode: "frontend" | "fullstack" | "server";
9
28
  runtimeTopology: "single-instance" | "multi-instance";
@@ -133,7 +152,10 @@ export interface AIIncidentSnapshot {
133
152
  hotspots: AIContextPacket["hotspots"];
134
153
  recommendations: string[];
135
154
  }
136
- export declare function createAIContextPacket(report: AIHealthReport, events: AIEvent[], latestDiagnostic?: Partial<AIDiagnostic>, reactiveTrace?: ReactiveTraceArtifact | null): AIContextPacket;
155
+ export declare function createAIContextPacket(report: AIHealthReport, events: AIEvent[], latestDiagnostic?: Partial<AIDiagnostic>, reactiveTrace?: ReactiveTraceArtifact | null, agentInput?: {
156
+ currentMode?: AIOperationMode;
157
+ rules?: AIRulesFile;
158
+ }): AIContextPacket;
137
159
  export declare function renderAIContextMarkdown(packet: AIContextPacket): string;
138
160
  export declare function createAIReleaseBrief(packet: AIContextPacket): AIReleaseBrief;
139
161
  export declare function renderAIReleaseBriefMarkdown(brief: AIReleaseBrief): string;
@@ -1,5 +1,9 @@
1
1
  import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
2
- export function createAIContextPacket(report, events, latestDiagnostic, reactiveTrace) {
2
+ import {
3
+ AI_OPERATION_MODES,
4
+ AI_TRANSPORT_CONTRACT
5
+ } from "./rules.js";
6
+ export function createAIContextPacket(report, events, latestDiagnostic, reactiveTrace, agentInput = {}) {
3
7
  const readiness = report.readiness ?? {
4
8
  deploy: { status: "ready", reasons: [] },
5
9
  scaling: { status: "not-applicable", reasons: [] }
@@ -7,6 +11,15 @@ export function createAIContextPacket(report, events, latestDiagnostic, reactive
7
11
  return {
8
12
  schemaVersion: GORSEE_AI_CONTEXT_SCHEMA_VERSION,
9
13
  generatedAt: new Date().toISOString(),
14
+ agent: {
15
+ currentMode: agentInput.currentMode ?? "inspect",
16
+ availableModes: AI_OPERATION_MODES,
17
+ transport: AI_TRANSPORT_CONTRACT,
18
+ rules: agentInput.rules ? {
19
+ path: agentInput.rules.path,
20
+ content: agentInput.rules.content
21
+ } : void 0
22
+ },
10
23
  app: report.app,
11
24
  summary: {
12
25
  headline: buildHeadline(report),
@@ -74,6 +87,13 @@ export function renderAIContextMarkdown(packet) {
74
87
  `- Runtime topology: ${packet.app.runtimeTopology}`,
75
88
  ""
76
89
  ] : [],
90
+ "## AI Agent",
91
+ "",
92
+ `- Current mode: ${packet.agent.currentMode}`,
93
+ `- Model traffic: ${packet.agent.transport.modelTraffic}`,
94
+ `- Bridge role: ${packet.agent.transport.bridgeRole}`,
95
+ `- Production role: ${packet.agent.transport.productionRole}`,
96
+ ...packet.agent.rules ? [`- Rules: ${packet.agent.rules.path}`, ""] : [""],
77
97
  "## Summary",
78
98
  "",
79
99
  `- ${packet.summary.headline}`,
@@ -140,6 +160,8 @@ export function renderAIContextMarkdown(packet) {
140
160
  if (packet.reactiveTrace.latestEventKind)
141
161
  lines.push(`- Latest event: ${packet.reactiveTrace.latestEventKind}`);
142
162
  }
163
+ if (packet.agent.rules)
164
+ lines.push("", "## AI Rules", "", `Source: ${packet.agent.rules.path}`, "", packet.agent.rules.content);
143
165
  if (packet.recommendations.length > 0) {
144
166
  lines.push("", "## Recommendations", "");
145
167
  for (const recommendation of packet.recommendations)
@@ -1,10 +1,13 @@
1
1
  import type { AIStorePaths } from "./store.js";
2
2
  import type { IDEProjection, IDEProjectionPaths } from "./ide.js";
3
+ import type { AIOperationMode } from "./rules.js";
3
4
  export interface IDEProjectionWatcherOptions {
4
5
  storePaths: AIStorePaths;
5
6
  projectionPaths: IDEProjectionPaths;
6
7
  intervalMs?: number;
7
8
  limit?: number;
9
+ cwd?: string;
10
+ mode?: AIOperationMode;
8
11
  onSync?: (projection: IDEProjection) => void | Promise<void>;
9
12
  }
10
13
  export interface IDEProjectionWatcher {
@@ -6,7 +6,11 @@ export function createIDEProjectionWatcher(options) {
6
6
  async syncOnce() {
7
7
  syncing = !0;
8
8
  try {
9
- const projection = await buildIDEProjection(options.storePaths, { limit: options.limit ?? 100 });
9
+ const projection = await buildIDEProjection(options.storePaths, {
10
+ limit: options.limit ?? 100,
11
+ cwd: options.cwd,
12
+ mode: options.mode
13
+ });
10
14
  await writeIDEProjection(options.projectionPaths, projection);
11
15
  if (options.onSync)
12
16
  await options.onSync(projection);
@@ -1,4 +1,12 @@
1
1
  import { createProjectContext } from "../runtime/project.js";
2
+ import {
3
+ mkdir,
4
+ writeFile
5
+ } from "node:fs/promises";
6
+ import {
7
+ basename,
8
+ join
9
+ } from "node:path";
2
10
  import {
3
11
  buildAIHealthReport,
4
12
  buildAIContextBundle,
@@ -11,9 +19,13 @@ import {
11
19
  createAIReleaseBrief,
12
20
  createAIMCPServer,
13
21
  createLineReader,
22
+ AI_OPERATION_MODES,
23
+ renderDefaultAIGuideMarkdown,
24
+ renderDefaultAIRulesMarkdown,
14
25
  readAIDiagnosticsSnapshot,
15
26
  readAIEvents,
16
27
  readReactiveTraceArtifact,
28
+ resolveAIRulesFile,
17
29
  renderAIIncidentBriefMarkdown,
18
30
  renderAIContextMarkdown,
19
31
  renderAIContextBundleMarkdown,
@@ -22,24 +34,30 @@ import {
22
34
  resolveAIStorePaths,
23
35
  resolveAISessionPackPaths,
24
36
  resolveIDEProjectionPaths,
37
+ writeAICheckpoint,
25
38
  writeAISessionPack,
26
39
  writeIDEProjection
27
40
  } from "../ai/index.js";
41
+ import { loadAppConfig, resolveAppMode } from "../runtime/app-config.js";
28
42
  export async function runAI(args, options = {}) {
29
43
  const subcommand = args[0] ?? "help", flags = parseAIFlags(args.slice(1)), { cwd } = createProjectContext(options), paths = resolveAIStorePaths(cwd);
30
44
  switch (subcommand) {
31
45
  case "framework":
32
46
  return runAIFramework(cwd, flags);
47
+ case "init":
48
+ return runAIInit(cwd, flags);
33
49
  case "tail":
34
50
  return runAITail(paths.eventsPath, flags);
35
51
  case "doctor":
36
- return runAIDoctor(paths, flags);
52
+ return runAIDoctor(cwd, paths, flags);
37
53
  case "replay":
38
54
  return runAIReplay(paths.eventsPath, flags);
39
55
  case "export":
40
56
  return runAIExport(cwd, paths, flags);
41
57
  case "pack":
42
58
  return runAIPack(cwd, paths, flags);
59
+ case "checkpoint":
60
+ return runAICheckpoint(cwd, paths, flags);
43
61
  case "ide-sync":
44
62
  return runAIIDESync(cwd, paths, flags);
45
63
  case "bridge":
@@ -59,6 +77,50 @@ async function runAIFramework(cwd, flags) {
59
77
  }
60
78
  console.log(JSON.stringify(packet, null, 2));
61
79
  }
80
+ async function runAIInit(cwd, flags) {
81
+ const appMode = resolveAppMode(await loadAppConfig(cwd)), projectName = basename(cwd), gorseeDir = join(cwd, ".gorsee"), agentDir = join(gorseeDir, "agent"), checkpointsDir = join(agentDir, "checkpoints"), rulesPath = join(gorseeDir, "rules.md"), guidePath = join(cwd, "GORSEE.md");
82
+ await mkdir(checkpointsDir, { recursive: !0 });
83
+ const writes = [], rulesExists = Boolean(await resolveAIRulesFile(cwd));
84
+ if (!rulesExists || flags.force) {
85
+ await writeFile(rulesPath, renderDefaultAIRulesMarkdown({ projectName, appMode }), "utf-8");
86
+ writes.push({ path: ".gorsee/rules.md", status: rulesExists ? "updated" : "created" });
87
+ } else
88
+ writes.push({ path: ".gorsee/rules.md", status: "kept" });
89
+ const guideExists = await Bun.file(guidePath).exists();
90
+ if (!guideExists || flags.force) {
91
+ await writeFile(guidePath, renderDefaultAIGuideMarkdown({ projectName, appMode }), "utf-8");
92
+ writes.push({ path: "GORSEE.md", status: guideExists ? "updated" : "created" });
93
+ } else
94
+ writes.push({ path: "GORSEE.md", status: "kept" });
95
+ if (flags.json) {
96
+ console.log(JSON.stringify({
97
+ projectName,
98
+ appMode,
99
+ scaffolded: writes,
100
+ checkpointsDir: ".gorsee/agent/checkpoints",
101
+ nextSteps: [
102
+ "gorsee ai framework --format markdown",
103
+ "gorsee ai checkpoint --mode inspect",
104
+ "gorsee check"
105
+ ]
106
+ }, null, 2));
107
+ return;
108
+ }
109
+ console.log(`
110
+ Gorsee AI Init
111
+ `);
112
+ console.log(` project -> ${projectName}`);
113
+ console.log(` app mode -> ${appMode}`);
114
+ for (const entry of writes)
115
+ console.log(` ${entry.status.padEnd(11, " ")}-> ${entry.path}`);
116
+ console.log(" prepared -> .gorsee/agent/checkpoints");
117
+ console.log();
118
+ console.log(" Next:");
119
+ console.log(" 1. Review .gorsee/rules.md and tailor it to the repository.");
120
+ console.log(" 2. Review GORSEE.md for local operator guidance.");
121
+ console.log(" 3. Run `gorsee ai checkpoint --mode inspect` before the first tracked AI session.");
122
+ console.log();
123
+ }
62
124
  async function runAITail(eventsPath, flags) {
63
125
  const events = await readAIEvents(eventsPath, { limit: flags.limit ?? 20 });
64
126
  if (flags.json) {
@@ -79,11 +141,15 @@ async function runAITail(eventsPath, flags) {
79
141
  }
80
142
  console.log();
81
143
  }
82
- async function runAIDoctor(paths, flags) {
83
- const report = await buildAIHealthReport(paths, { limit: flags.limit ?? 200 }), reactiveTrace = await readReactiveTraceArtifact(paths.reactiveTracePath);
144
+ async function runAIDoctor(cwd, paths, flags) {
145
+ const report = await buildAIHealthReport(paths, { limit: flags.limit ?? 200 }), reactiveTrace = await readReactiveTraceArtifact(paths.reactiveTracePath), rules = await resolveAIRulesFile(cwd);
84
146
  if (flags.json) {
85
147
  console.log(JSON.stringify({
86
148
  ...report,
149
+ agent: {
150
+ currentMode: flags.mode ?? "inspect",
151
+ rulesPath: rules?.path
152
+ },
87
153
  reactiveTrace: reactiveTrace ? {
88
154
  schemaVersion: reactiveTrace.schemaVersion,
89
155
  nodes: reactiveTrace.nodes.length,
@@ -101,6 +167,9 @@ async function runAIDoctor(paths, flags) {
101
167
  console.log(` Diagnostics: ${report.diagnostics.total}`);
102
168
  console.log(` Errors: ${report.diagnostics.errors}`);
103
169
  console.log(` Warnings: ${report.diagnostics.warnings}`);
170
+ console.log(` AI mode: ${flags.mode ?? "inspect"}`);
171
+ if (rules?.path)
172
+ console.log(` Rules: ${rules.path}`);
104
173
  console.log(` Deploy readiness: ${report.readiness.deploy.status}`);
105
174
  console.log(` Scaling readiness: ${report.readiness.scaling.status}`);
106
175
  if (report.events.latest)
@@ -186,7 +255,7 @@ async function runAIReplay(eventsPath, flags) {
186
255
  }
187
256
  async function runAIExport(cwd, paths, flags) {
188
257
  if (flags.bundle) {
189
- const bundle = await buildAIContextBundle(cwd, paths, { limit: flags.limit ?? 200 });
258
+ const bundle = await buildAIContextBundle(cwd, paths, { limit: flags.limit ?? 200, mode: flags.mode ?? "inspect" });
190
259
  if ((flags.format ?? "json") === "markdown") {
191
260
  console.log(renderAIContextBundleMarkdown(bundle));
192
261
  return;
@@ -194,7 +263,10 @@ async function runAIExport(cwd, paths, flags) {
194
263
  console.log(JSON.stringify(bundle, null, 2));
195
264
  return;
196
265
  }
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);
266
+ 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 }), rules = await resolveAIRulesFile(cwd), packet = createAIContextPacket(report, events, diagnostics?.latest, reactiveTrace, {
267
+ currentMode: flags.mode ?? "inspect",
268
+ rules
269
+ });
198
270
  if (flags.brief === "release") {
199
271
  const brief = createAIReleaseBrief(packet);
200
272
  if ((flags.format ?? "json") === "markdown") {
@@ -223,7 +295,8 @@ async function runAIPack(cwd, paths, flags) {
223
295
  const result = await writeAISessionPack(cwd, paths, {
224
296
  enabled: !0,
225
297
  outDir: resolveAISessionPackPaths(cwd).outDir,
226
- limit: flags.limit ?? 200
298
+ limit: flags.limit ?? 200,
299
+ mode: flags.mode ?? "inspect"
227
300
  });
228
301
  if (flags.json) {
229
302
  console.log(JSON.stringify({
@@ -260,15 +333,52 @@ async function runAIPack(cwd, paths, flags) {
260
333
  console.log(` snippets -> ${result.bundle.snippets.length}`);
261
334
  console.log();
262
335
  }
336
+ async function runAICheckpoint(cwd, paths, flags) {
337
+ const result = await writeAICheckpoint(cwd, paths, {
338
+ name: flags.name,
339
+ mode: flags.mode ?? "inspect",
340
+ limit: flags.limit ?? 200,
341
+ maxSnippets: 6
342
+ });
343
+ if (flags.json) {
344
+ console.log(JSON.stringify({
345
+ createdAt: result.metadata.createdAt,
346
+ name: result.metadata.name,
347
+ mode: result.metadata.mode,
348
+ bundleJsonPath: result.paths.bundleJsonPath,
349
+ bundleMarkdownPath: result.paths.bundleMarkdownPath,
350
+ metadataPath: result.paths.metadataPath,
351
+ latestPointerPath: result.paths.latestPointerPath,
352
+ rulesPath: result.metadata.rulesPath,
353
+ snippets: result.bundle.snippets.length
354
+ }, null, 2));
355
+ return;
356
+ }
357
+ console.log(`
358
+ Gorsee AI Checkpoint
359
+ `);
360
+ console.log(` name -> ${result.metadata.name}`);
361
+ console.log(` mode -> ${result.metadata.mode}`);
362
+ console.log(` bundle json -> ${result.paths.bundleJsonPath}`);
363
+ console.log(` bundle md -> ${result.paths.bundleMarkdownPath}`);
364
+ console.log(` metadata -> ${result.paths.metadataPath}`);
365
+ console.log(` latest -> ${result.paths.latestPointerPath}`);
366
+ if (result.metadata.rulesPath)
367
+ console.log(` rules -> ${result.metadata.rulesPath}`);
368
+ console.log(` snippets -> ${result.bundle.snippets.length}`);
369
+ console.log();
370
+ }
263
371
  async function runAIIDESync(cwd, paths, flags) {
264
- const projection = await buildIDEProjection(paths, { limit: flags.limit ?? 100 }), projectionPaths = resolveIDEProjectionPaths(cwd);
372
+ const projection = await buildIDEProjection(paths, { limit: flags.limit ?? 100, cwd, mode: flags.mode ?? "inspect" }), projectionPaths = resolveIDEProjectionPaths(cwd);
265
373
  await writeIDEProjection(projectionPaths, projection);
266
374
  if (flags.watch) {
267
375
  createIDEProjectionWatcher({
268
376
  storePaths: paths,
269
377
  projectionPaths,
270
378
  limit: flags.limit ?? 100,
271
- intervalMs: flags.intervalMs ?? 1000
379
+ intervalMs: flags.intervalMs ?? 1000,
380
+ cwd,
381
+ mode: flags.mode ?? "inspect"
272
382
  }).start();
273
383
  console.log(`
274
384
  Gorsee AI IDE Sync --watch
@@ -310,11 +420,13 @@ async function runAIMCP(paths, flags) {
310
420
  }).serve(createLineReader(process.stdin), process.stdout);
311
421
  }
312
422
  function parseAIFlags(args) {
313
- const flags = { json: !1, bundle: !1, watch: !1 };
423
+ const flags = { json: !1, bundle: !1, watch: !1, force: !1 };
314
424
  for (let i = 0;i < args.length; i++) {
315
425
  const arg = args[i];
316
426
  if (arg === "--json")
317
427
  flags.json = !0;
428
+ if (arg === "--force")
429
+ flags.force = !0;
318
430
  if (arg === "--bundle")
319
431
  flags.bundle = !0;
320
432
  if (arg === "--watch")
@@ -339,6 +451,13 @@ function parseAIFlags(args) {
339
451
  if (brief === "release" || brief === "incident")
340
452
  flags.brief = brief;
341
453
  }
454
+ if (arg === "--mode") {
455
+ const mode = args[i + 1];
456
+ if (AI_OPERATION_MODES.some((entry) => entry.mode === mode))
457
+ flags.mode = mode;
458
+ }
459
+ if (arg === "--name")
460
+ flags.name = args[i + 1];
342
461
  }
343
462
  return flags;
344
463
  }
@@ -347,6 +466,7 @@ function printAIHelp() {
347
466
  gorsee ai <subcommand>
348
467
  `);
349
468
  console.log(" Subcommands:");
469
+ console.log(" init Create local AI rules and operator scaffold files");
350
470
  console.log(" framework Export canonical framework context for cold-start agents");
351
471
  console.log(" tail Read recent structured AI events");
352
472
  console.log(" doctor Summarize diagnostics and recent incidents");
@@ -354,6 +474,7 @@ function printAIHelp() {
354
474
  console.log(" export Export a compact AI context packet or bundle");
355
475
  console.log(" Use --brief release|incident for verdict-oriented summaries");
356
476
  console.log(" pack Write the latest agent-ready session pack to disk");
477
+ console.log(" checkpoint Write an explicit AI checkpoint with operation-mode metadata");
357
478
  console.log(" ide-sync Write IDE-friendly diagnostics/events/context files");
358
479
  console.log(" bridge Start local HTTP bridge for IDE/agent ingestion");
359
480
  console.log(" mcp Start stdio MCP server over local AI state");
@@ -365,5 +486,8 @@ function printAIHelp() {
365
486
  console.log(" --bundle Include ranked code snippets in export output");
366
487
  console.log(" --watch Keep IDE projection files in sync");
367
488
  console.log(" --interval <ms> Watch/poll interval for ide-sync --watch");
489
+ console.log(" --mode <mode> inspect | propose | apply | operate");
490
+ console.log(" --name <value> Human-readable checkpoint name");
491
+ console.log(" --force Overwrite AI scaffold files when they already exist");
368
492
  console.log();
369
493
  }
@@ -9,7 +9,8 @@ import { rewriteCanonicalImportsInProject, rewriteLegacyLoadersInProject } from
9
9
  import {
10
10
  configureAIObservability,
11
11
  emitAIDiagnostic,
12
- emitAIEvent
12
+ emitAIEvent,
13
+ resolveAIRulesFile
13
14
  } from "../ai/index.js";
14
15
  import { loadAppConfig, resolveAIConfig, resolveAppMode, resolveRuntimeTopology } from "../runtime/app-config.js";
15
16
  const MAX_FILE_LINES = 500;
@@ -502,6 +503,35 @@ async function checkOriginPlaceholderPolicy(cwd) {
502
503
  }
503
504
  return issues;
504
505
  }
506
+ async function checkAIContracts(cwd) {
507
+ const issues = [], aiEnabled = (await loadAppConfig(cwd)).ai?.enabled ?? !1, rules = await resolveAIRulesFile(cwd);
508
+ if (aiEnabled && !rules)
509
+ issues.push({
510
+ code: "W928",
511
+ file: "app.config.ts",
512
+ message: "AI observability is enabled but no local AI rules file was found",
513
+ fix: "Add .gorsee/rules.md (preferred) or GORSEE.md so agents and operator workflows share an explicit local contract"
514
+ });
515
+ const latestAgentPacketSource = await tryReadFile(join(cwd, ".gorsee", "agent", "latest.json")), latestCheckpointSource = await tryReadFile(join(cwd, ".gorsee", "agent", "checkpoints", "latest.json"));
516
+ try {
517
+ const latestPacket = latestAgentPacketSource ? JSON.parse(latestAgentPacketSource) : null, latestCheckpoint = latestCheckpointSource ? JSON.parse(latestCheckpointSource) : null, currentMode = latestPacket?.agent?.currentMode, mutatingMode = currentMode === "apply" || currentMode === "operate", hasMatchingCheckpoint = latestCheckpoint?.mode === currentMode;
518
+ if (mutatingMode && !hasMatchingCheckpoint)
519
+ issues.push({
520
+ code: "W929",
521
+ file: ".gorsee/agent/latest.json",
522
+ message: `Latest AI packet reports mutating mode "${currentMode}" without a matching explicit checkpoint`,
523
+ fix: `Run \`gorsee ai checkpoint --mode ${currentMode}\` before or during mutating AI workflows so the session state is preserved explicitly`
524
+ });
525
+ } catch {
526
+ issues.push({
527
+ code: "W929",
528
+ file: ".gorsee/agent/latest.json",
529
+ message: "Could not parse latest AI packet or checkpoint metadata for mutating-mode enforcement",
530
+ fix: "Regenerate AI packet/checkpoint artifacts so mutating-mode workflows stay inspectable"
531
+ });
532
+ }
533
+ return issues;
534
+ }
505
535
  async function projectUsesServerFunctions(files, astFacts) {
506
536
  for (const file of files) {
507
537
  const ast = astFacts.get(file);
@@ -635,6 +665,9 @@ export async function checkProject(options = {}) {
635
665
  const placeholderIssues = await checkOriginPlaceholderPolicy(cwd);
636
666
  for (const issue of placeholderIssues)
637
667
  pushIssue(result, issue, strictSecurity);
668
+ const aiIssues = await checkAIContracts(cwd);
669
+ for (const issue of aiIssues)
670
+ pushIssue(result, issue, strictSecurity);
638
671
  if (runTypeScript) {
639
672
  const tsc = Bun.spawn(["bun", "x", "tsc", "--noEmit"], {
640
673
  cwd,
@@ -372,11 +372,17 @@ gorsee check Type + safety + structure check
372
372
  gorsee worker Run canonical server-mode worker entry
373
373
  gorsee check --rewrite-imports --rewrite-loaders
374
374
  Normalize canonical imports and loader aliases before auditing
375
+ gorsee ai init Scaffold local AI rules, operator guide, and checkpoints
375
376
  gorsee ai framework Export canonical framework context for cold-start agents
377
+ gorsee ai tail Inspect recent structured AI events
376
378
  gorsee ai doctor Summarize AI diagnostics and incidents
377
379
  gorsee ai replay Reconstruct recent correlated AI event timeline
378
380
  gorsee ai export Export a compact agent-ready context packet
381
+ gorsee ai pack Write the latest grounded AI session pack to disk
382
+ gorsee ai checkpoint
383
+ Record an explicit named AI workflow checkpoint
379
384
  gorsee ai ide-sync Write IDE-friendly diagnostics/events/context files
385
+ gorsee ai bridge Accept trusted local AI event ingestion
380
386
  gorsee ai mcp Expose local AI state as a stdio MCP server
381
387
  gorsee routes List all routes
382
388
  gorsee migrate Run database migrations
@@ -385,6 +391,7 @@ gorsee generate X Generate CRUD for entity X
385
391
 
386
392
  - For installed apps, prefer \`gorsee upgrade\` for the full version bump + rewrite + verification flow.
387
393
  - Use \`gorsee upgrade --check --report docs/upgrade-report.json\` for a dry-run audit without installation.
394
+ - When AI workflows are enabled, run \`gorsee ai init\` once and tailor \`.gorsee/rules.md\` before the first tracked session.
388
395
 
389
396
  ## Error Codes
390
397
 
@@ -12,7 +12,7 @@ const args = process.argv.slice(2), command = args[0], COMMANDS = {
12
12
  deploy: "Generate deploy config (vercel/fly/cloudflare/netlify/docker)",
13
13
  test: "Run tests (unit/integration/e2e)",
14
14
  docs: "Generate API documentation from routes",
15
- ai: "AI-first tooling: framework, tail, doctor, bridge, mcp",
15
+ ai: "AI-first tooling: init, framework, tail, doctor, export, pack, checkpoint, ide-sync, bridge, mcp",
16
16
  upgrade: "Upgrade Gorsee.js with migration audit and canonical rewrites",
17
17
  help: "Show this help message"
18
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gorsee",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "AI-first reactive full-stack TypeScript framework for deterministic human and agent collaboration",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.9",
@@ -74,6 +74,7 @@
74
74
  "dependency:policy": "node scripts/dependency-contract-check.mjs",
75
75
  "deploy:policy": "node scripts/deploy-contract-check.mjs",
76
76
  "api:policy": "node scripts/api-stability-check.mjs",
77
+ "cli:policy": "node scripts/cli-contract-check.mjs",
77
78
  "adoption:policy": "node scripts/adoption-proof-check.mjs",
78
79
  "ai:policy": "node scripts/ai-policy-check.mjs",
79
80
  "dx:policy": "node scripts/dx-policy-check.mjs",
@@ -105,7 +106,7 @@
105
106
  "coverage:audit": "node scripts/coverage-audit-check.mjs",
106
107
  "repo:policy": "node scripts/repo-policy-check.mjs",
107
108
  "ci:policy": "node scripts/ci-policy-check.mjs",
108
- "verify:security": "bun run check && bun run product:policy && bun run dependency:policy && bun run deploy:policy && bun run api:policy && bun run adoption:policy && bun run ai:policy && bun run dx:policy && bun run maturity:policy && bun run top-tier:exit && bun run runtime:policy && bun run runtime:security:policy && bun run benchmarks:policy && bun run benchmarks:realworld:check && bun run examples:policy && bun run proof:policy && bun run critical:surface && bun run coverage:audit && bun run repo:policy && bun run ci:policy && bun run compiler:promotion:check && bun run build:promotion:check && bun run backend:switch:evidence:check && bun run backend:default-switch:review:check && bun run backend:candidate:rollout:check && bun run compiler:default:rehearsal:check && bun run build:default:rehearsal:check && bun run test:security && bun run test:critical-surface && bun run test:confidence",
109
+ "verify:security": "bun run check && bun run product:policy && bun run dependency:policy && bun run deploy:policy && bun run api:policy && bun run cli:policy && bun run adoption:policy && bun run ai:policy && bun run dx:policy && bun run maturity:policy && bun run top-tier:exit && bun run runtime:policy && bun run runtime:security:policy && bun run benchmarks:policy && bun run benchmarks:realworld:check && bun run examples:policy && bun run proof:policy && bun run critical:surface && bun run coverage:audit && bun run repo:policy && bun run ci:policy && bun run compiler:promotion:check && bun run build:promotion:check && bun run backend:switch:evidence:check && bun run backend:default-switch:review:check && bun run backend:candidate:rollout:check && bun run compiler:default:rehearsal:check && bun run build:default:rehearsal:check && bun run test:security && bun run test:critical-surface && bun run test:confidence",
109
110
  "check": "tsc --noEmit",
110
111
  "install:matrix": "node scripts/install-matrix-check.mjs",
111
112
  "dev": "bun run src/dev.ts",