Split app-server protocol Grit boundaries

This commit is contained in:
murashit 2026-06-26 07:40:16 +09:00
parent 5ad3c18d34
commit 1a90cf977d
5 changed files with 130 additions and 75 deletions

View file

@ -13,7 +13,27 @@
},
{
"path": "./scripts/lint/no-app-server-protocol-boundary-imports.grit",
"includes": ["**/src/**/*.ts", "**/src/**/*.tsx", "!**/src/app-server/**/*.ts", "!**/src/app-server/**/*.tsx"]
"includes": [
"**/src/**/*.ts",
"**/src/**/*.tsx",
"!**/src/app-server/**/*.ts",
"!**/src/app-server/**/*.tsx",
"!**/src/features/chat/app-server/inbound/notification-plan.ts",
"!**/src/features/chat/app-server/mappers/message-stream/turn-items.ts",
"!**/src/features/chat/app-server/inbound/handler.ts",
"!**/src/features/chat/app-server/inbound/routing.ts"
]
},
{
"path": "./scripts/lint/no-chat-app-server-turn-protocol-imports.grit",
"includes": [
"**/src/features/chat/app-server/inbound/notification-plan.ts",
"**/src/features/chat/app-server/mappers/message-stream/turn-items.ts"
]
},
{
"path": "./scripts/lint/no-chat-app-server-request-protocol-imports.grit",
"includes": ["**/src/features/chat/app-server/inbound/handler.ts", "**/src/features/chat/app-server/inbound/routing.ts"]
},
{
"path": "./scripts/lint/no-generated-app-server-boundary-imports.grit",

View file

@ -15,40 +15,10 @@ or {
$stmt <: contains `$source` where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$"
},
or {
{
not { $filename <: r".*/src/features/chat/app-server/(?:inbound/notification-plan|mappers/message-stream/turn-items)\.ts$" },
not { $filename <: r".*/src/features/chat/app-server/inbound/(?:handler|routing)\.ts$" },
register_diagnostic(span=$stmt, message="Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.", severity="error")
},
{
$filename <: r".*/src/features/chat/app-server/(?:inbound/notification-plan|mappers/message-stream/turn-items)\.ts$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/turn|src/app-server/protocol/turn)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.", severity="error")
},
{
$filename <: r".*/src/features/chat/app-server/inbound/(?:handler|routing)\.ts$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/server-requests|src/app-server/protocol/server-requests)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server request handling may consume server request protocol projections only. Convert app-server payloads to chat pending request domain models at this boundary.", severity="error")
}
}
},
`require($source)` as $stmt where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
not { $filename <: r".*/src/features/chat/app-server/(?:inbound/notification-plan|mappers/message-stream/turn-items)\.ts$" },
not { $filename <: r".*/src/features/chat/app-server/inbound/(?:handler|routing)\.ts$" },
register_diagnostic(span=$stmt, message="Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.", severity="error")
},
`require($source)` as $stmt where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
$filename <: r".*/src/features/chat/app-server/(?:inbound/notification-plan|mappers/message-stream/turn-items)\.ts$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/turn|src/app-server/protocol/turn)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.", severity="error")
},
`require($source)` as $stmt where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
$filename <: r".*/src/features/chat/app-server/inbound/(?:handler|routing)\.ts$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/server-requests|src/app-server/protocol/server-requests)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server request handling may consume server request protocol projections only. Convert app-server payloads to chat pending request domain models at this boundary.", severity="error")
register_diagnostic(span=$stmt, message="Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.", severity="error")
}
}

View file

@ -0,0 +1,26 @@
language js
private pattern js_module_reference() {
or {
JsImport(),
JsExportNamedFromClause(),
JsExportFromClause(),
TsImportType(),
JsImportCallExpression()
}
}
or {
js_module_reference() as $stmt where {
$stmt <: contains `$source` where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/server-requests|src/app-server/protocol/server-requests)(?:/.*)?[\"']$" }
},
register_diagnostic(span=$stmt, message="Chat app-server request handling may consume server request protocol projections only. Convert app-server payloads to chat pending request domain models at this boundary.", severity="error")
},
`require($source)` as $stmt where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/server-requests|src/app-server/protocol/server-requests)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server request handling may consume server request protocol projections only. Convert app-server payloads to chat pending request domain models at this boundary.", severity="error")
}
}

View file

@ -0,0 +1,26 @@
language js
private pattern js_module_reference() {
or {
JsImport(),
JsExportNamedFromClause(),
JsExportFromClause(),
TsImportType(),
JsImportCallExpression()
}
}
or {
js_module_reference() as $stmt where {
$stmt <: contains `$source` where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/turn|src/app-server/protocol/turn)(?:/.*)?[\"']$" }
},
register_diagnostic(span=$stmt, message="Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.", severity="error")
},
`require($source)` as $stmt where {
$source <: r"^[\"'](?:(?:\.\./)+app-server/protocol|src/app-server/protocol)/[^/\"']+(?:/.*)?[\"']$",
not { $source <: r"^[\"'](?:(?:\.\./)+app-server/protocol/turn|src/app-server/protocol/turn)(?:/.*)?[\"']$" },
register_diagnostic(span=$stmt, message="Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.", severity="error")
}
}

View file

@ -452,6 +452,49 @@ import type { TurnItem } from "../../../../app-server/protocol/turn";
export type Item = TurnItem;
`.trimStart(),
);
await writeFile(
path.join(cwd, "src/features/chat/panel/surface/message-stream-presenter.ts"),
`
import { appServerUserInputResponse } from "../../../../../app-server/protocol/server-requests";
export const response = appServerUserInputResponse;
`.trimStart(),
);
await writeFile(
path.join(cwd, "src/features/chat/app-server/inbound/app-server-logs.ts"),
`
import { appServerUserInputResponse } from "../../../../app-server/protocol/server-requests";
export const response = appServerUserInputResponse;
`.trimStart(),
);
const report = biomeLint(
[
"src/features/chat/application/pending-requests/pending-request-actions.ts",
"src/features/chat/application/threads/history-controller.ts",
"src/features/chat/panel/surface/message-stream-presenter.ts",
"src/features/chat/app-server/inbound/app-server-logs.ts",
],
cwd,
);
expect(pluginMessages(report, "src/features/chat/application/pending-requests/pending-request-actions.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/application/threads/history-controller.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/panel/surface/message-stream-presenter.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/app-server/inbound/app-server-logs.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
});
it("keeps chat app-server ingestion on app-server turn protocol only", async () => {
const cwd = await tempBiomeWorkspace(["no-chat-app-server-turn-protocol-imports.grit"]);
await writeFile(
path.join(cwd, "src/features/chat/app-server/inbound/notification-plan.ts"),
`
@ -470,22 +513,21 @@ import type { TurnItem } from "../../../../../app-server/protocol/turn";
export type Item = TurnItem;
`.trimStart(),
);
await writeFile(
path.join(cwd, "src/features/chat/panel/surface/message-stream-presenter.ts"),
`
import { appServerUserInputResponse } from "../../../../../app-server/protocol/server-requests";
export const response = appServerUserInputResponse;
`.trimStart(),
const report = biomeLint(
["src/features/chat/app-server/inbound/notification-plan.ts", "src/features/chat/app-server/mappers/message-stream/turn-items.ts"],
cwd,
);
await writeFile(
path.join(cwd, "src/features/chat/app-server/inbound/app-server-logs.ts"),
`
import { appServerUserInputResponse } from "../../../../app-server/protocol/server-requests";
export const response = appServerUserInputResponse;
`.trimStart(),
);
expect(pluginMessages(report, "src/features/chat/app-server/inbound/notification-plan.ts")).toEqual([
"Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.",
"Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.",
]);
expect(pluginDiagnostics(report, "src/features/chat/app-server/mappers/message-stream/turn-items.ts")).toEqual([]);
});
it("keeps chat app-server request handling on server request protocol only", async () => {
const cwd = await tempBiomeWorkspace(["no-chat-app-server-request-protocol-imports.grit"]);
await writeFile(
path.join(cwd, "src/features/chat/app-server/inbound/handler.ts"),
`
@ -503,37 +545,8 @@ export const response = appServerUserInputResponse;
`.trimStart(),
);
const report = biomeLint(
[
"src/features/chat/application/pending-requests/pending-request-actions.ts",
"src/features/chat/application/threads/history-controller.ts",
"src/features/chat/app-server/inbound/notification-plan.ts",
"src/features/chat/app-server/mappers/message-stream/turn-items.ts",
"src/features/chat/panel/surface/message-stream-presenter.ts",
"src/features/chat/app-server/inbound/app-server-logs.ts",
"src/features/chat/app-server/inbound/handler.ts",
"src/features/chat/app-server/inbound/routing.ts",
],
cwd,
);
const report = biomeLint(["src/features/chat/app-server/inbound/handler.ts", "src/features/chat/app-server/inbound/routing.ts"], cwd);
expect(pluginMessages(report, "src/features/chat/application/pending-requests/pending-request-actions.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/application/threads/history-controller.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/app-server/inbound/notification-plan.ts")).toEqual([
"Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.",
"Chat app-server ingestion and message-stream conversion may consume the app-server turn protocol only. Convert other protocol payloads to local or domain models at the boundary.",
]);
expect(pluginDiagnostics(report, "src/features/chat/app-server/mappers/message-stream/turn-items.ts")).toEqual([]);
expect(pluginMessages(report, "src/features/chat/panel/surface/message-stream-presenter.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/app-server/inbound/app-server-logs.ts")).toEqual([
"Source modules outside app-server must use domain models and app-server services instead of app-server protocol modules. Chat ingestion and message-stream conversion may consume app-server turn protocol at the boundary; feature state and UI must use Panel-owned models.",
]);
expect(pluginMessages(report, "src/features/chat/app-server/inbound/handler.ts")).toEqual([
"Chat app-server request handling may consume server request protocol projections only. Convert app-server payloads to chat pending request domain models at this boundary.",
]);