@webpresso/agent-kit 3.3.3 → 3.3.4
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.
Potentially problematic release.
This version of @webpresso/agent-kit might be problematic. Click here for more details.
- package/THIRD-PARTY-NOTICES.md +12 -10
- package/catalog/agent/rules/changeset-release.md +15 -4
- package/catalog/agent/rules/managed-tool-binaries.md +67 -0
- package/catalog/agent/rules/parallel-orchestration-quota.md +99 -1
- package/catalog/agent/rules/pre-implementation.md +36 -20
- package/catalog/agent/rules/rtk-routing.md +22 -16
- package/catalog/agent/skills/autopilot/SKILL.md +4 -3
- package/catalog/agent/skills/ultragoal/SKILL.md +11 -9
- package/dist/esm/audit/hook-surface.js +5 -1
- package/dist/esm/audit/repo-guardrails.d.ts +8 -0
- package/dist/esm/audit/repo-guardrails.js +71 -1
- package/dist/esm/blueprint/core/parser.js +38 -12
- package/dist/esm/blueprint/execution/artifacts.js +8 -4
- package/dist/esm/blueprint/execution/frontmatter-keys.d.ts +17 -0
- package/dist/esm/blueprint/execution/frontmatter-keys.js +24 -0
- package/dist/esm/blueprint/execution/metadata.js +8 -4
- package/dist/esm/blueprint/lifecycle/audit.d.ts +21 -0
- package/dist/esm/blueprint/lifecycle/audit.js +89 -3
- package/dist/esm/blueprint/lifecycle/review-provenance.js +63 -10
- package/dist/esm/blueprint/lifecycle/rollout-anchor.d.ts +22 -0
- package/dist/esm/blueprint/lifecycle/rollout-anchor.js +37 -1
- package/dist/esm/blueprint/markdown/blocked-line.d.ts +49 -0
- package/dist/esm/blueprint/markdown/blocked-line.js +63 -0
- package/dist/esm/blueprint/markdown/helpers.js +10 -4
- package/dist/esm/blueprint/tracked-document/parser.js +3 -3
- package/dist/esm/blueprint/trust/gate-row.d.ts +55 -0
- package/dist/esm/blueprint/trust/gate-row.js +113 -0
- package/dist/esm/blueprint/trust/promotion.d.ts +17 -0
- package/dist/esm/blueprint/trust/promotion.js +19 -19
- package/dist/esm/build/atomic-file-copy.d.ts +32 -0
- package/dist/esm/build/atomic-file-copy.js +44 -0
- package/dist/esm/build/vendor-oxlint-plugins.d.ts +8 -0
- package/dist/esm/build/vendor-oxlint-plugins.js +53 -0
- package/dist/esm/cli/commands/blueprint/mutations.d.ts +15 -0
- package/dist/esm/cli/commands/blueprint/mutations.js +8 -2
- package/dist/esm/cli/commands/compile.d.ts +13 -0
- package/dist/esm/cli/commands/compile.js +182 -62
- package/dist/esm/cli/commands/format.js +17 -1
- package/dist/esm/cli/commands/gain/index.js +10 -3
- package/dist/esm/cli/commands/init/gitignore-patcher.js +6 -0
- package/dist/esm/cli/commands/init/index.js +29 -48
- package/dist/esm/cli/commands/init/mcp-spec.d.ts +48 -13
- package/dist/esm/cli/commands/init/mcp-spec.js +86 -30
- package/dist/esm/cli/commands/init/merge.js +30 -10
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +56 -31
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +180 -43
- package/dist/esm/cli/commands/init/scaffolders/rtk/index.d.ts +17 -5
- package/dist/esm/cli/commands/init/scaffolders/rtk/index.js +56 -75
- package/dist/esm/cli/commands/init/scaffolders/runtime-check/index.js +7 -6
- package/dist/esm/cli/commands/init/untracked-collision.d.ts +12 -1
- package/dist/esm/cli/commands/init/untracked-collision.js +23 -1
- package/dist/esm/cli/commands/pr-help.js +1 -1
- package/dist/esm/cli/commands/pr.js +18 -4
- package/dist/esm/cli/commands/review.js +60 -6
- package/dist/esm/cli/commands/worktree/router-dispatch.d.ts +24 -2
- package/dist/esm/cli/commands/worktree/router-dispatch.js +80 -48
- package/dist/esm/cli/commands/worktree/router.js +5 -2
- package/dist/esm/cli/direct-provider-launch.js +12 -4
- package/dist/esm/compiler/flatten.d.ts +10 -1
- package/dist/esm/compiler/flatten.js +14 -4
- package/dist/esm/compose/admin-blocks-registry-integrity.d.ts +22 -0
- package/dist/esm/compose/admin-blocks-registry-integrity.js +90 -0
- package/dist/esm/compose/compose.d.ts +8 -0
- package/dist/esm/compose/compose.js +115 -8
- package/dist/esm/compose/ops-report-schema.js +17 -3
- package/dist/esm/compose/registry-resolve.d.ts +17 -0
- package/dist/esm/compose/registry-resolve.js +78 -11
- package/dist/esm/config/oxlint/graphql-conventions.js +2 -5
- package/dist/esm/config/oxlint/import-hygiene.js +21 -8
- package/dist/esm/config/oxlint/oxlint-config.fixture.d.ts +1 -1
- package/dist/esm/config/oxlint/oxlint-config.fixture.js +2 -3
- package/dist/esm/config/oxlint/oxlintrc.d.ts +5 -7
- package/dist/esm/config/oxlint/oxlintrc.js +18 -21
- package/dist/esm/config/oxlint/path-roles.js +53 -0
- package/dist/esm/config/oxlint/query-patterns.js +2 -5
- package/dist/esm/daemon/domains/blueprint-exec-ledger.d.ts +86 -0
- package/dist/esm/daemon/domains/blueprint-exec-ledger.js +134 -0
- package/dist/esm/daemon/domains/blueprint-exec.d.ts +106 -0
- package/dist/esm/daemon/domains/blueprint-exec.js +161 -0
- package/dist/esm/daemon/domains/launch.d.ts +25 -0
- package/dist/esm/daemon/domains/launch.js +30 -1
- package/dist/esm/daemon/handlers/blueprints-handlers.d.ts +12 -1
- package/dist/esm/daemon/handlers/blueprints-handlers.js +148 -6
- package/dist/esm/daemon/handlers/product.d.ts +10 -0
- package/dist/esm/daemon/handlers/product.js +10 -1
- package/dist/esm/daemon/methods.d.ts +21 -1
- package/dist/esm/daemon/methods.js +20 -0
- package/dist/esm/daemon/protocol/contract.d.ts +58 -0
- package/dist/esm/daemon/protocol/contract.js +38 -0
- package/dist/esm/daemon/server.js +7 -0
- package/dist/esm/docs-linter/blueprint-plan.js +2 -2
- package/dist/esm/errors/wp-error.js +21 -2
- package/dist/esm/hooks/doctor.d.ts +11 -0
- package/dist/esm/hooks/doctor.js +114 -45
- package/dist/esm/hooks/pretool-guard/dev-routing.js +1 -1
- package/dist/esm/hooks/pretool-guard/rtk-rewrite.d.ts +24 -0
- package/dist/esm/hooks/pretool-guard/rtk-rewrite.js +50 -0
- package/dist/esm/hooks/pretool-guard/runner.js +6 -0
- package/dist/esm/hooks/status/index.js +1 -1
- package/dist/esm/mcp/blueprint/_shared/lifecycle.js +39 -11
- package/dist/esm/mcp/blueprint/handlers/review-log.d.ts +14 -7
- package/dist/esm/mcp/blueprint/handlers/review-log.js +46 -22
- package/dist/esm/mcp/blueprint/registration.js +1 -1
- package/dist/esm/mcp/tools/_shared/redact.d.ts +22 -0
- package/dist/esm/mcp/tools/_shared/redact.js +114 -8
- package/dist/esm/mcp/tools/gain.js +28 -2
- package/dist/esm/mcp/tools/worktree.js +65 -3
- package/dist/esm/mcp/tools/wp-ui-compose.js +38 -4
- package/dist/esm/mcp/tools/wp-ui-preview.js +14 -7
- package/dist/esm/review/lifecycle-writers.d.ts +76 -0
- package/dist/esm/review/lifecycle-writers.js +330 -0
- package/dist/esm/review/subject.js +66 -32
- package/dist/esm/status/snapshot.d.ts +5 -0
- package/dist/esm/status/snapshot.js +27 -2
- package/dist/esm/test/shard-durations.json +0 -1
- package/dist/esm/test-helpers/global-setup.js +38 -3
- package/dist/esm/tool-runtime/managed-rtk.d.ts +44 -0
- package/dist/esm/tool-runtime/managed-rtk.js +275 -0
- package/dist/esm/tool-runtime/resolve-runner.js +18 -194
- package/dist/esm/utils/package-root.d.ts +32 -0
- package/dist/esm/utils/package-root.js +82 -0
- package/dist/esm/worktrees/git-metadata.d.ts +41 -0
- package/dist/esm/worktrees/git-metadata.js +48 -0
- package/package.json +16 -21
- package/dist/esm/config/oxlint/code-safety.d.ts +0 -18
- package/dist/esm/config/oxlint/foundation-purity.d.ts +0 -21
- package/dist/esm/config/oxlint/graphql-conventions.d.ts +0 -23
- package/dist/esm/config/oxlint/import-hygiene.d.ts +0 -34
- package/dist/esm/config/oxlint/index.d.ts +0 -22
- package/dist/esm/config/oxlint/index.js +0 -28
- package/dist/esm/config/oxlint/monorepo-paths.d.ts +0 -22
- package/dist/esm/config/oxlint/query-patterns.d.ts +0 -24
- package/dist/esm/config/oxlint/testing-quality.d.ts +0 -35
- package/dist/esm/config/oxlint/tier-boundaries.d.ts +0 -35
- package/dist/esm/output-transforms/rulesync.d.ts +0 -2
- package/dist/esm/output-transforms/rulesync.js +0 -79
|
@@ -16,19 +16,33 @@ export const opsReportSectionSchema = z
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
|
+
const finiteNumber = z.number().finite();
|
|
20
|
+
const cellValue = z.union([z.string(), finiteNumber]);
|
|
19
21
|
export const opsReportMetricSchema = z
|
|
20
22
|
.object({
|
|
21
23
|
label: z.string().min(1),
|
|
22
|
-
value:
|
|
24
|
+
value: cellValue,
|
|
23
25
|
})
|
|
24
26
|
.strict();
|
|
25
27
|
export const opsReportTableSchema = z
|
|
26
28
|
.object({
|
|
27
29
|
title: z.string().optional(),
|
|
28
30
|
headers: z.array(z.string()).min(1),
|
|
29
|
-
rows: z.array(z.array(
|
|
31
|
+
rows: z.array(z.array(cellValue)),
|
|
30
32
|
})
|
|
31
|
-
.strict()
|
|
33
|
+
.strict()
|
|
34
|
+
.superRefine((table, ctx) => {
|
|
35
|
+
const expected = table.headers.length;
|
|
36
|
+
for (const [rowIndex, row] of table.rows.entries()) {
|
|
37
|
+
if (row.length !== expected) {
|
|
38
|
+
ctx.addIssue({
|
|
39
|
+
code: "custom",
|
|
40
|
+
message: `row has ${row.length} cell(s); expected ${expected} to match headers`,
|
|
41
|
+
path: ["rows", rowIndex],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
32
46
|
/**
|
|
33
47
|
* Minimal ops-report IR. Not a general page AST.
|
|
34
48
|
* Nesting under sections is rejected by the section schema (flat only).
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Local reader capability floor for project registries (agent-kit consumer).
|
|
4
|
+
* Bump in the same PR as catalog/compose/admin-blocks-registry.json major/minor
|
|
5
|
+
* advances. Does not import @webpresso/schema (SEA / nondeterminism lock).
|
|
6
|
+
*/
|
|
7
|
+
export declare const READER_REGISTRY_VERSION: "1.0.0";
|
|
2
8
|
export declare const blockRegistrySchema: z.ZodObject<{
|
|
3
9
|
$schema: z.ZodOptional<z.ZodString>;
|
|
4
10
|
version: z.ZodString;
|
|
@@ -30,6 +36,17 @@ export interface ResolvedBlockRegistry {
|
|
|
30
36
|
readonly webpressoPresentWithoutRegistry: boolean;
|
|
31
37
|
}
|
|
32
38
|
export declare function defaultSnapshotPath(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Whether a loaded project registry is readable by this agent-kit consumer.
|
|
41
|
+
* - registry.version major must match the reader major
|
|
42
|
+
* - if registry.minVersion is set, reader must be >= that floor (semver order)
|
|
43
|
+
*/
|
|
44
|
+
export declare function isProjectRegistryCompatibleWithReader(registry: BlockRegistry, readerVersion?: string): {
|
|
45
|
+
readonly ok: true;
|
|
46
|
+
} | {
|
|
47
|
+
readonly ok: false;
|
|
48
|
+
readonly reason: string;
|
|
49
|
+
};
|
|
33
50
|
/**
|
|
34
51
|
* Two-tier registry resolution (v0):
|
|
35
52
|
* 1. Nearest project `.webpresso/` (within git/webpressorc boundary) — if it has
|
|
@@ -5,6 +5,12 @@ import { resolvePackageAssetPreferred } from "#utils/package-assets.js";
|
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
const REGISTRY_RELATIVE = join("generated", "frontend", "blocks", "registry.json");
|
|
7
7
|
const MAX_WALK = 48;
|
|
8
|
+
/**
|
|
9
|
+
* Local reader capability floor for project registries (agent-kit consumer).
|
|
10
|
+
* Bump in the same PR as catalog/compose/admin-blocks-registry.json major/minor
|
|
11
|
+
* advances. Does not import @webpresso/schema (SEA / nondeterminism lock).
|
|
12
|
+
*/
|
|
13
|
+
export const READER_REGISTRY_VERSION = "1.0.0";
|
|
8
14
|
/** Stop climbing past these markers (mirrors project-root clamps elsewhere). */
|
|
9
15
|
function isProjectBoundary(dir) {
|
|
10
16
|
return existsSync(join(dir, ".git")) || existsSync(join(dir, ".webpressorc.json"));
|
|
@@ -82,6 +88,53 @@ function loadRegistryFile(path) {
|
|
|
82
88
|
throw new Error(`Failed to load block registry at ${path}: ${detail}`, { cause: error });
|
|
83
89
|
}
|
|
84
90
|
}
|
|
91
|
+
function parseSemver(version) {
|
|
92
|
+
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
93
|
+
if (!match)
|
|
94
|
+
return null;
|
|
95
|
+
return {
|
|
96
|
+
major: Number(match[1]),
|
|
97
|
+
minor: Number(match[2]),
|
|
98
|
+
patch: Number(match[3]),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Whether a loaded project registry is readable by this agent-kit consumer.
|
|
103
|
+
* - registry.version major must match the reader major
|
|
104
|
+
* - if registry.minVersion is set, reader must be >= that floor (semver order)
|
|
105
|
+
*/
|
|
106
|
+
export function isProjectRegistryCompatibleWithReader(registry, readerVersion = READER_REGISTRY_VERSION) {
|
|
107
|
+
const reader = parseSemver(readerVersion);
|
|
108
|
+
if (!reader) {
|
|
109
|
+
return { ok: false, reason: `reader version "${readerVersion}" is not semver` };
|
|
110
|
+
}
|
|
111
|
+
const produced = parseSemver(registry.version);
|
|
112
|
+
if (!produced) {
|
|
113
|
+
return { ok: false, reason: `registry version "${registry.version}" is not semver` };
|
|
114
|
+
}
|
|
115
|
+
if (produced.major !== reader.major) {
|
|
116
|
+
return {
|
|
117
|
+
ok: false,
|
|
118
|
+
reason: `registry major ${produced.major} incompatible with reader major ${reader.major} (${readerVersion})`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (registry.minVersion !== undefined) {
|
|
122
|
+
const min = parseSemver(registry.minVersion);
|
|
123
|
+
if (!min) {
|
|
124
|
+
return { ok: false, reason: `registry minVersion "${registry.minVersion}" is not semver` };
|
|
125
|
+
}
|
|
126
|
+
const belowMin = reader.major < min.major ||
|
|
127
|
+
(reader.major === min.major && reader.minor < min.minor) ||
|
|
128
|
+
(reader.major === min.major && reader.minor === min.minor && reader.patch < min.patch);
|
|
129
|
+
if (belowMin) {
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
reason: `reader ${readerVersion} is below registry minVersion ${registry.minVersion}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { ok: true };
|
|
137
|
+
}
|
|
85
138
|
/**
|
|
86
139
|
* Two-tier registry resolution (v0):
|
|
87
140
|
* 1. Nearest project `.webpresso/` (within git/webpressorc boundary) — if it has
|
|
@@ -103,20 +156,34 @@ export function resolveBlockRegistry(options = {}) {
|
|
|
103
156
|
if (webpressoRoot) {
|
|
104
157
|
const projectPath = join(webpressoRoot, REGISTRY_RELATIVE);
|
|
105
158
|
if (existsSync(projectPath)) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
registry
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
159
|
+
try {
|
|
160
|
+
const registry = loadRegistryFile(projectPath);
|
|
161
|
+
const compat = isProjectRegistryCompatibleWithReader(registry);
|
|
162
|
+
if (!compat.ok) {
|
|
163
|
+
warnings.push(`Project registry at ${projectPath} incompatible with reader ${READER_REGISTRY_VERSION} (${compat.reason}); using catalog snapshot.`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
return {
|
|
167
|
+
registry,
|
|
168
|
+
source: "project",
|
|
169
|
+
registryVersion: registry.version,
|
|
170
|
+
path: projectPath,
|
|
171
|
+
warnings,
|
|
172
|
+
webpressoPresentWithoutRegistry: false,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
// Producer codegen can advance ahead of this consumer's schema; prefer
|
|
178
|
+
// snapshot over hard-failing MCP tools on version skew.
|
|
179
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
180
|
+
warnings.push(`Project registry at ${projectPath} failed validation (${detail}); using catalog snapshot. Regenerate or align registry schema.`);
|
|
181
|
+
}
|
|
115
182
|
}
|
|
116
183
|
}
|
|
117
184
|
const snapshotPath = options.snapshotPath ?? defaultSnapshotPath();
|
|
118
185
|
const registry = loadRegistryFile(snapshotPath);
|
|
119
|
-
if (webpressoRoot) {
|
|
186
|
+
if (webpressoRoot && warnings.length === 0) {
|
|
120
187
|
warnings.push(`Project has .webpresso/ at ${webpressoRoot} but no ${join(".webpresso", REGISTRY_RELATIVE)}; using catalog snapshot ${registry.version}. Run schema frontend codegen / converge to materialize a project registry.`);
|
|
121
188
|
}
|
|
122
189
|
return {
|
|
@@ -125,7 +192,7 @@ export function resolveBlockRegistry(options = {}) {
|
|
|
125
192
|
registryVersion: registry.version,
|
|
126
193
|
path: snapshotPath,
|
|
127
194
|
warnings,
|
|
128
|
-
webpressoPresentWithoutRegistry: webpressoRoot !== null,
|
|
195
|
+
webpressoPresentWithoutRegistry: webpressoRoot !== null && !existsSync(join(webpressoRoot, REGISTRY_RELATIVE)),
|
|
129
196
|
};
|
|
130
197
|
}
|
|
131
198
|
export function blockNamesForView(registry, view) {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// causes runtime errors: "field 'user' not found in type: 'query_root'"
|
|
8
8
|
//
|
|
9
9
|
// This rule scans template literals and string literals for known singular patterns and reports them.
|
|
10
|
+
import { isWebAppSurface, normalizeFilename } from "./path-roles.js";
|
|
10
11
|
// Mapping of singular table patterns to their correct plural/actual GraphQL field names.
|
|
11
12
|
// Format: [singular, correct, description]
|
|
12
13
|
const SINGULAR_TABLE_RULES = [
|
|
@@ -76,9 +77,6 @@ const INLINE_GRAPHQL_EXEMPT_PATH_SEGMENTS = [
|
|
|
76
77
|
"/packages/sdk/schema-engine/src/emitters/",
|
|
77
78
|
"/packages/feature/app-core/src/daemon/",
|
|
78
79
|
];
|
|
79
|
-
function normalizeFilename(filename) {
|
|
80
|
-
return typeof filename === "string" ? filename.replaceAll("\\", "/") : "";
|
|
81
|
-
}
|
|
82
80
|
function getFilename(context) {
|
|
83
81
|
if (typeof context.getFilename === "function") {
|
|
84
82
|
return normalizeFilename(context.getFilename());
|
|
@@ -92,9 +90,8 @@ function isClientQuerySurface(filename) {
|
|
|
92
90
|
if (INLINE_GRAPHQL_EXEMPT_PATH_SEGMENTS.some((segment) => normalized.includes(segment))) {
|
|
93
91
|
return false;
|
|
94
92
|
}
|
|
95
|
-
const isWebAppSurface = normalized.includes("/apps/web/") && normalized.includes("/app/");
|
|
96
93
|
const isFeatureSurface = normalized.includes("/packages/feature/") && normalized.includes("/src/");
|
|
97
|
-
return isWebAppSurface || isFeatureSurface;
|
|
94
|
+
return isWebAppSurface(normalized) || isFeatureSurface;
|
|
98
95
|
}
|
|
99
96
|
function getNodeStart(node) {
|
|
100
97
|
if (Array.isArray(node?.range) && typeof node.range[0] === "number") {
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
// - no-src-path-imports
|
|
5
5
|
// - no-relative-mock-paths
|
|
6
6
|
// - no-forbidden-package-imports
|
|
7
|
+
import { isAgentKitSeaTreeFile, isPlatformAppFile, isSdkPackageFile, normalizeFilename, } from "./path-roles.js";
|
|
8
|
+
export { isAgentKitSeaTreeFile, isPlatformAppFile, isSdkPackageFile, normalizeFilename, } from "./path-roles.js";
|
|
7
9
|
const CROSS_PACKAGE_SEGMENT = /(?:^|\/)(packages|apps|tooling|infra|webpresso)\//;
|
|
8
10
|
function isRelativeParentPath(source) {
|
|
9
11
|
return typeof source === "string" && source.includes("../");
|
|
@@ -32,9 +34,6 @@ function reportCrossPackageImport(context, node) {
|
|
|
32
34
|
message: "Do not reach into another package/app with a relative filesystem import. Add a proper package export and import it via the package name.",
|
|
33
35
|
});
|
|
34
36
|
}
|
|
35
|
-
function normalizeFilename(filename) {
|
|
36
|
-
return typeof filename === "string" ? filename.replaceAll("\\", "/") : "";
|
|
37
|
-
}
|
|
38
37
|
function getFilename(context) {
|
|
39
38
|
if (typeof context.getFilename === "function") {
|
|
40
39
|
return normalizeFilename(context.getFilename());
|
|
@@ -46,12 +45,16 @@ function checkStaticModuleSource(node, callback) {
|
|
|
46
45
|
return;
|
|
47
46
|
callback(node.source.value, node.source);
|
|
48
47
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
48
|
+
/** Package imports forbidden in agent-kit SEA surfaces (schema + ui paint kits). */
|
|
49
|
+
export function isSeaForbiddenPackageImport(source) {
|
|
50
|
+
if (typeof source !== "string")
|
|
51
|
+
return false;
|
|
52
|
+
return (source === "@webpresso/schema" ||
|
|
53
|
+
source.startsWith("@webpresso/schema/") ||
|
|
54
|
+
source === "@webpresso/ui" ||
|
|
55
|
+
source.startsWith("@webpresso/ui/"));
|
|
54
56
|
}
|
|
57
|
+
export const SEA_FORBIDDEN_IMPORT_MESSAGE = "Agent-kit SEA surfaces (compose / wp_ui_*) must not import `@webpresso/schema` or `@webpresso/ui`. Use the two-tier block registry snapshot/project file and local Zod/HTML paint instead (offline / nondeterminism lock).";
|
|
55
58
|
function isSchemaEngineImport(source) {
|
|
56
59
|
return typeof source === "string" && source.startsWith("@webpresso/schema/engine/");
|
|
57
60
|
}
|
|
@@ -147,6 +150,16 @@ const noForbiddenPackageImports = {
|
|
|
147
150
|
function checkImport(source, node) {
|
|
148
151
|
if (typeof source !== "string")
|
|
149
152
|
return;
|
|
153
|
+
// Agent-kit SEA / offline compose — ban before monorepo platform allow rules.
|
|
154
|
+
// Consumers still get this rule via shipped oxlintrc; monorepo apps do not match
|
|
155
|
+
// isAgentKitSeaTreeFile so public schema imports remain allowed there.
|
|
156
|
+
if (isAgentKitSeaTreeFile(filename) && isSeaForbiddenPackageImport(source)) {
|
|
157
|
+
context.report({
|
|
158
|
+
node,
|
|
159
|
+
message: SEA_FORBIDDEN_IMPORT_MESSAGE,
|
|
160
|
+
});
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
150
163
|
if (isPlatformAppFile(filename) &&
|
|
151
164
|
isSchemaEngineImport(source) &&
|
|
152
165
|
source !== "@webpresso/schema/engine/api") {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { config } from "
|
|
1
|
+
import { config } from "@webpresso/agent-config/oxlint";
|
|
2
2
|
export default config;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { config } from "
|
|
2
|
-
//
|
|
3
|
-
// import { config } from 'webpresso/oxlint'
|
|
1
|
+
import { config } from "@webpresso/agent-config/oxlint";
|
|
2
|
+
// Shape parity for folded config consumers (agent-config is the SSOT).
|
|
4
3
|
export default config;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Compiled plugin module basenames shipped next to the generated oxlintrc.json.
|
|
3
|
-
*
|
|
4
|
-
* test in `oxlintrc.test.ts`, which asserts one entry per registered plugin).
|
|
3
|
+
* Must match agent-config policy plugins (guarded by vendor + parity tests).
|
|
5
4
|
*/
|
|
6
5
|
export declare const OXLINT_PLUGIN_BASENAMES: readonly ["code-safety", "foundation-purity", "graphql-conventions", "import-hygiene", "monorepo-paths", "query-patterns", "testing-quality", "tier-boundaries"];
|
|
7
6
|
/** jsPlugins specifiers, sibling-relative to the shipped oxlintrc.json. */
|
|
8
7
|
export declare const OXLINT_JS_PLUGIN_FILES: readonly string[];
|
|
9
8
|
/**
|
|
10
9
|
* Standard ignore patterns for every webpresso consumer: build output, vendored
|
|
11
|
-
* deps, generated reports, and the regenerated agent-surface directories.
|
|
12
|
-
* are project-relative. Truly repo-specific extras belong in a consumer-local
|
|
13
|
-
* `.oxlintignore`, never here.
|
|
10
|
+
* deps, generated reports, and the regenerated agent-surface directories.
|
|
14
11
|
*/
|
|
15
12
|
export declare const STANDARD_IGNORE_PATTERNS: readonly string[];
|
|
16
13
|
export interface ResolvedOxlintRc {
|
|
@@ -18,9 +15,10 @@ export interface ResolvedOxlintRc {
|
|
|
18
15
|
readonly rules: Readonly<Record<string, "error">>;
|
|
19
16
|
readonly ignorePatterns: readonly string[];
|
|
20
17
|
}
|
|
18
|
+
/** Rule map from agent-config SSOT (error severity for inject). */
|
|
19
|
+
export declare const rules: Readonly<Record<string, "error">>;
|
|
21
20
|
/**
|
|
22
21
|
* Build the resolved oxlint config object that ships as `oxlintrc.json`. Pure:
|
|
23
|
-
* the build-time generator serializes this return value verbatim
|
|
24
|
-
* parity test asserts it against the live `rules`/`plugins` exports.
|
|
22
|
+
* the build-time generator serializes this return value verbatim.
|
|
25
23
|
*/
|
|
26
24
|
export declare function buildOxlintrc(): ResolvedOxlintRc;
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolved, consumer-ready oxlint configuration (Tier-1 DRY model).
|
|
3
3
|
*
|
|
4
|
-
* agent-kit ships ONE resolved `.oxlintrc.json` — generated
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `oxlint.config.ts` and no `oxlint` dependency; the linter version, plugins,
|
|
8
|
-
* rules, and standard ignores are all gated to @webpresso/agent-kit.
|
|
4
|
+
* agent-kit ships ONE resolved `.oxlintrc.json` — generated at build time into
|
|
5
|
+
* `dist/esm/config/oxlint/oxlintrc.json` — and `wp lint` points oxlint at it via
|
|
6
|
+
* `--config` for consumers without a local oxlint config.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
8
|
+
* Plugin *bodies* are authored in `@webpresso/agent-config/oxlint/*` (consumer
|
|
9
|
+
* SSOT). Build vendors compiled sibling `.js` next to oxlintrc.json so inject
|
|
10
|
+
* needs no runtime agent-config dependency. Monorepos with their own lint
|
|
11
|
+
* config load `@webpresso/agent-config/oxlint/*` package names directly.
|
|
12
|
+
*
|
|
13
|
+
* Two oxlint resolution facts (verified against oxlint 1.67) make inject work:
|
|
14
|
+
* - `jsPlugins` are resolved relative to the CONFIG FILE's directory
|
|
15
|
+
* (`./<plugin>.js` siblings of the shipped JSON).
|
|
16
|
+
* - `ignorePatterns` apply relative to the LINTED project (cwd).
|
|
18
17
|
*/
|
|
19
|
-
import { rules } from "
|
|
18
|
+
import { rules as agentConfigRules } from "@webpresso/agent-config/oxlint";
|
|
20
19
|
/**
|
|
21
20
|
* Compiled plugin module basenames shipped next to the generated oxlintrc.json.
|
|
22
|
-
*
|
|
23
|
-
* test in `oxlintrc.test.ts`, which asserts one entry per registered plugin).
|
|
21
|
+
* Must match agent-config policy plugins (guarded by vendor + parity tests).
|
|
24
22
|
*/
|
|
25
23
|
export const OXLINT_PLUGIN_BASENAMES = [
|
|
26
24
|
"code-safety",
|
|
@@ -36,9 +34,7 @@ export const OXLINT_PLUGIN_BASENAMES = [
|
|
|
36
34
|
export const OXLINT_JS_PLUGIN_FILES = OXLINT_PLUGIN_BASENAMES.map((name) => `./${name}.js`);
|
|
37
35
|
/**
|
|
38
36
|
* Standard ignore patterns for every webpresso consumer: build output, vendored
|
|
39
|
-
* deps, generated reports, and the regenerated agent-surface directories.
|
|
40
|
-
* are project-relative. Truly repo-specific extras belong in a consumer-local
|
|
41
|
-
* `.oxlintignore`, never here.
|
|
37
|
+
* deps, generated reports, and the regenerated agent-surface directories.
|
|
42
38
|
*/
|
|
43
39
|
export const STANDARD_IGNORE_PATTERNS = [
|
|
44
40
|
"dist",
|
|
@@ -53,10 +49,11 @@ export const STANDARD_IGNORE_PATTERNS = [
|
|
|
53
49
|
".opencode",
|
|
54
50
|
".runtime",
|
|
55
51
|
];
|
|
52
|
+
/** Rule map from agent-config SSOT (error severity for inject). */
|
|
53
|
+
export const rules = agentConfigRules;
|
|
56
54
|
/**
|
|
57
55
|
* Build the resolved oxlint config object that ships as `oxlintrc.json`. Pure:
|
|
58
|
-
* the build-time generator serializes this return value verbatim
|
|
59
|
-
* parity test asserts it against the live `rules`/`plugins` exports.
|
|
56
|
+
* the build-time generator serializes this return value verbatim.
|
|
60
57
|
*/
|
|
61
58
|
export function buildOxlintrc() {
|
|
62
59
|
return {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Shared path classifiers for webpresso oxlint policy plugins.
|
|
4
|
+
* Pure functions only — no AST. Consumers resolve plugins from
|
|
5
|
+
* `@webpresso/agent-config/oxlint/*`; these markers must match real trees.
|
|
6
|
+
*/
|
|
7
|
+
/** Normalize Windows paths for substring role checks. */
|
|
8
|
+
export function normalizeFilename(filename) {
|
|
9
|
+
return typeof filename === "string" ? filename.replaceAll("\\", "/") : "";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Offline / SEA-shaped agent-kit surfaces (compose + UI MCP tools).
|
|
13
|
+
* Monorepo apps never use these path segments.
|
|
14
|
+
*/
|
|
15
|
+
export function isAgentKitSeaTreeFile(filename) {
|
|
16
|
+
const n = normalizeFilename(filename);
|
|
17
|
+
if (n.includes("/node_modules/"))
|
|
18
|
+
return false;
|
|
19
|
+
return n.includes("/src/compose/") || n.includes("/src/mcp/tools/wp-ui-");
|
|
20
|
+
}
|
|
21
|
+
/** Platform web apps: real monorepo layout + legacy `/apps/web/`. */
|
|
22
|
+
export function isPlatformWebFile(filename) {
|
|
23
|
+
const n = normalizeFilename(filename);
|
|
24
|
+
if (n.includes("/node_modules/"))
|
|
25
|
+
return false;
|
|
26
|
+
return n.includes("/apps/platform/web/") || n.includes("/apps/web/");
|
|
27
|
+
}
|
|
28
|
+
/** Platform workers: real monorepo layout + legacy `/apps/workers/`. */
|
|
29
|
+
export function isPlatformWorkerFile(filename) {
|
|
30
|
+
const n = normalizeFilename(filename);
|
|
31
|
+
if (n.includes("/node_modules/"))
|
|
32
|
+
return false;
|
|
33
|
+
return n.includes("/apps/platform/workers/") || n.includes("/apps/workers/");
|
|
34
|
+
}
|
|
35
|
+
/** Platform apps (web or worker) for import-hygiene schema-surface rules. */
|
|
36
|
+
export function isPlatformAppFile(filename) {
|
|
37
|
+
return isPlatformWebFile(filename) || isPlatformWorkerFile(filename);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Client UI surfaces for GraphQL/query-pattern rules.
|
|
41
|
+
* Real monorepo: apps/platform/web/.../app/; legacy apps/web/.../app/.
|
|
42
|
+
*/
|
|
43
|
+
export function isWebAppSurface(filename) {
|
|
44
|
+
const n = normalizeFilename(filename);
|
|
45
|
+
if (n.includes("/node_modules/"))
|
|
46
|
+
return false;
|
|
47
|
+
if (!n.includes("/app/"))
|
|
48
|
+
return false;
|
|
49
|
+
return n.includes("/apps/platform/web/") || n.includes("/apps/web/");
|
|
50
|
+
}
|
|
51
|
+
export function isSdkPackageFile(filename) {
|
|
52
|
+
return normalizeFilename(filename).includes("/packages/sdk/");
|
|
53
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
+
import { isWebAppSurface, normalizeFilename } from "./path-roles.js";
|
|
2
3
|
const QUERY_HOOK_NAMES = new Set(["useQuery", "useSuspenseQuery", "useInfiniteQuery"]);
|
|
3
|
-
function normalizeFilename(filename) {
|
|
4
|
-
return typeof filename === "string" ? filename.replaceAll("\\", "/") : "";
|
|
5
|
-
}
|
|
6
4
|
function getFilename(context) {
|
|
7
5
|
if (typeof context.getFilename === "function") {
|
|
8
6
|
return normalizeFilename(context.getFilename());
|
|
@@ -15,9 +13,8 @@ function isClientQuerySurface(filename) {
|
|
|
15
13
|
return false;
|
|
16
14
|
if (normalized.includes("/.webpresso/generated/"))
|
|
17
15
|
return false;
|
|
18
|
-
const isWebAppSurface = normalized.includes("/apps/web/") && normalized.includes("/app/");
|
|
19
16
|
const isFeatureSurface = normalized.includes("/packages/feature/") && normalized.includes("/src/");
|
|
20
|
-
return isWebAppSurface || isFeatureSurface;
|
|
17
|
+
return isWebAppSurface(normalized) || isFeatureSurface;
|
|
21
18
|
}
|
|
22
19
|
function getCalleeName(callee) {
|
|
23
20
|
if (!callee)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blueprint exec run ledger: durable job ↔ PTY session ↔ blueprint attribution.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists separately from the launch ledger: a launch handle is
|
|
5
|
+
* single-use and is consumed the moment Rust claims it, and the PTY reaper
|
|
6
|
+
* reports that *a* session ended but not which blueprint it belonged to.
|
|
7
|
+
* Neither can answer "what is this terminal running?" after a UI restart. A
|
|
8
|
+
* job id that outlives both can.
|
|
9
|
+
*
|
|
10
|
+
* Rows are deliberately env-free and argv-free: this ledger is readable by the
|
|
11
|
+
* webview, so it must never carry launch material.
|
|
12
|
+
*/
|
|
13
|
+
export declare const BLUEPRINT_EXEC_JOB_STATES: readonly ["preparing", "running", "terminal"];
|
|
14
|
+
export type BlueprintExecJobState = (typeof BLUEPRINT_EXEC_JOB_STATES)[number];
|
|
15
|
+
export type BlueprintExecJob = {
|
|
16
|
+
readonly jobId: string;
|
|
17
|
+
readonly slug: string;
|
|
18
|
+
readonly taskId: string | null;
|
|
19
|
+
/** Opaque single-use launch handle; never the composed argv or env. */
|
|
20
|
+
readonly launchHandle: string;
|
|
21
|
+
readonly sessionId: number | null;
|
|
22
|
+
readonly startedAt: number;
|
|
23
|
+
readonly state: BlueprintExecJobState;
|
|
24
|
+
};
|
|
25
|
+
export type RegisterBlueprintExecJobInput = {
|
|
26
|
+
readonly slug: string;
|
|
27
|
+
readonly taskId: string | null;
|
|
28
|
+
readonly launchHandle: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Bounded, insertion-ordered job store.
|
|
32
|
+
*
|
|
33
|
+
* Complexity: `register`, `bindSession`, `markTerminal`, and `get` are all
|
|
34
|
+
* Map-keyed O(1). Eviction is O(1) too — terminal job ids are appended to a
|
|
35
|
+
* FIFO queue as they terminate, so making room pops the front instead of
|
|
36
|
+
* rescanning the map. `list` is O(#jobs) over a capped map.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Construction options. Shared by the class and {@link createBlueprintExecLedger}
|
|
40
|
+
* so the factory's public surface cannot drift away from what the constructor
|
|
41
|
+
* actually accepts.
|
|
42
|
+
*/
|
|
43
|
+
export type BlueprintExecLedgerOptions = {
|
|
44
|
+
readonly maxJobs?: number;
|
|
45
|
+
readonly staleUnboundMs?: number;
|
|
46
|
+
/** Injectable clock (tests). */
|
|
47
|
+
readonly now?: () => number;
|
|
48
|
+
};
|
|
49
|
+
export declare class BlueprintExecLedger {
|
|
50
|
+
private readonly byJobId;
|
|
51
|
+
/** FIFO of job ids that reached `terminal`, oldest first. */
|
|
52
|
+
private readonly terminalOrder;
|
|
53
|
+
private readonly maxJobs;
|
|
54
|
+
private readonly staleUnboundMs;
|
|
55
|
+
private readonly now;
|
|
56
|
+
constructor(options?: BlueprintExecLedgerOptions);
|
|
57
|
+
/** Evict the oldest terminal job. O(1) amortized via the FIFO queue. */
|
|
58
|
+
private evictOneTerminal;
|
|
59
|
+
/**
|
|
60
|
+
* Last-resort reclaim: the oldest job that never bound a session and whose
|
|
61
|
+
* launch handle can no longer be claimed.
|
|
62
|
+
*
|
|
63
|
+
* Without this, a daemon that only ever prepared launches which were never
|
|
64
|
+
* claimed (a crashing Rust peer) would wedge at the cap forever, because
|
|
65
|
+
* nothing would ever transition those jobs to terminal.
|
|
66
|
+
*
|
|
67
|
+
* O(#jobs) and only on the eviction path when the terminal queue is empty.
|
|
68
|
+
*/
|
|
69
|
+
private evictOneStaleUnbound;
|
|
70
|
+
register(input: RegisterBlueprintExecJobInput): {
|
|
71
|
+
readonly jobId: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Bind the spawned PTY session to a job. Rust-only caller.
|
|
75
|
+
*
|
|
76
|
+
* Single-assignment: a second bind for the same job is rejected so a
|
|
77
|
+
* compromised or buggy peer cannot re-point an existing job at another
|
|
78
|
+
* session.
|
|
79
|
+
*/
|
|
80
|
+
bindSession(jobId: string, sessionId: number): BlueprintExecJob;
|
|
81
|
+
markTerminal(jobId: string): BlueprintExecJob | null;
|
|
82
|
+
get(jobId: string): BlueprintExecJob | undefined;
|
|
83
|
+
list(): readonly BlueprintExecJob[];
|
|
84
|
+
size(): number;
|
|
85
|
+
}
|
|
86
|
+
export declare function createBlueprintExecLedger(options?: BlueprintExecLedgerOptions): BlueprintExecLedger;
|