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 +13 -1
- package/dist-pkg/ai/bundle.d.ts +2 -0
- package/dist-pkg/ai/bundle.js +5 -1
- package/dist-pkg/ai/checkpoint.d.ts +33 -0
- package/dist-pkg/ai/checkpoint.js +50 -0
- package/dist-pkg/ai/framework-context.d.ts +7 -0
- package/dist-pkg/ai/framework-context.js +61 -4
- package/dist-pkg/ai/ide.d.ts +4 -0
- package/dist-pkg/ai/ide.js +8 -1
- package/dist-pkg/ai/index.d.ts +2 -0
- package/dist-pkg/ai/index.js +12 -0
- package/dist-pkg/ai/rules.d.ts +28 -0
- package/dist-pkg/ai/rules.js +118 -0
- package/dist-pkg/ai/session-pack.d.ts +2 -0
- package/dist-pkg/ai/session-pack.js +2 -1
- package/dist-pkg/ai/summary.d.ts +23 -1
- package/dist-pkg/ai/summary.js +23 -1
- package/dist-pkg/ai/watch.d.ts +3 -0
- package/dist-pkg/ai/watch.js +5 -1
- package/dist-pkg/cli/cmd-ai.js +133 -9
- package/dist-pkg/cli/cmd-check.js +34 -1
- package/dist-pkg/cli/framework-md.js +7 -0
- package/dist-pkg/cli/index.js +1 -1
- package/package.json +3 -2
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
|
|
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.
|
package/dist-pkg/ai/bundle.d.ts
CHANGED
|
@@ -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;
|
package/dist-pkg/ai/bundle.js
CHANGED
|
@@ -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 }),
|
|
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: [
|
|
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,
|
|
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
|
`);
|
package/dist-pkg/ai/ide.d.ts
CHANGED
|
@@ -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>;
|
package/dist-pkg/ai/ide.js
CHANGED
|
@@ -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
|
package/dist-pkg/ai/index.d.ts
CHANGED
|
@@ -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";
|
package/dist-pkg/ai/index.js
CHANGED
|
@@ -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 = [
|
package/dist-pkg/ai/summary.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/dist-pkg/ai/summary.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { GORSEE_AI_CONTEXT_SCHEMA_VERSION } from "./contracts.js";
|
|
2
|
-
|
|
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)
|
package/dist-pkg/ai/watch.d.ts
CHANGED
|
@@ -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 {
|
package/dist-pkg/ai/watch.js
CHANGED
|
@@ -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, {
|
|
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);
|
package/dist-pkg/cli/cmd-ai.js
CHANGED
|
@@ -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
|
|
package/dist-pkg/cli/index.js
CHANGED
|
@@ -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.
|
|
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",
|