@webpresso/agent-kit 3.3.3 → 3.3.5
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/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/agents.js +126 -26
- 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/dossier.js +41 -1
- 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 +11 -0
- package/dist/esm/build/vendor-oxlint-plugins.js +48 -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 +32 -52
- 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.d.ts +1 -0
- package/dist/esm/cli/commands/review.js +137 -7
- package/dist/esm/cli/commands/sync.d.ts +8 -6
- package/dist/esm/cli/commands/sync.js +11 -9
- 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 +19 -31
- package/dist/esm/config/oxlint/path-roles.js +53 -0
- package/dist/esm/config/oxlint/query-patterns.js +2 -5
- package/dist/esm/content/dispatch.js +4 -0
- package/dist/esm/content/loader.d.ts +1 -1
- package/dist/esm/content/loader.js +10 -6
- package/dist/esm/content/skill-policy.d.ts +11 -0
- package/dist/esm/content/skill-policy.js +33 -0
- 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 +68 -5
- 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/pretool-guard/validators/worktree-discipline.js +62 -3
- 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/authority.js +56 -1
- package/dist/esm/review/delivery-verifier.d.ts +4 -0
- package/dist/esm/review/delivery-verifier.js +9 -1
- 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/symlinker/consumers.d.ts +3 -1
- package/dist/esm/symlinker/consumers.js +7 -1
- package/dist/esm/symlinker/unified-sync.d.ts +3 -3
- package/dist/esm/symlinker/unified-sync.js +88 -11
- package/dist/esm/test/shard-durations.json +0 -2
- 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/cli/commands/init/scaffolders/subagents/index.d.ts +0 -6
- package/dist/esm/cli/commands/init/scaffolders/subagents/index.js +0 -77
- 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
|
+
* SSOT: `@webpresso/agent-config/oxlint` `OXLINT_POLICY_PLUGIN_BASENAMES`.
|
|
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,44 +1,31 @@
|
|
|
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 { OXLINT_POLICY_PLUGIN_BASENAMES, 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
|
+
* SSOT: `@webpresso/agent-config/oxlint` `OXLINT_POLICY_PLUGIN_BASENAMES`.
|
|
24
22
|
*/
|
|
25
|
-
export const OXLINT_PLUGIN_BASENAMES =
|
|
26
|
-
"code-safety",
|
|
27
|
-
"foundation-purity",
|
|
28
|
-
"graphql-conventions",
|
|
29
|
-
"import-hygiene",
|
|
30
|
-
"monorepo-paths",
|
|
31
|
-
"query-patterns",
|
|
32
|
-
"testing-quality",
|
|
33
|
-
"tier-boundaries",
|
|
34
|
-
];
|
|
23
|
+
export const OXLINT_PLUGIN_BASENAMES = OXLINT_POLICY_PLUGIN_BASENAMES;
|
|
35
24
|
/** jsPlugins specifiers, sibling-relative to the shipped oxlintrc.json. */
|
|
36
25
|
export const OXLINT_JS_PLUGIN_FILES = OXLINT_PLUGIN_BASENAMES.map((name) => `./${name}.js`);
|
|
37
26
|
/**
|
|
38
27
|
* 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.
|
|
28
|
+
* deps, generated reports, and the regenerated agent-surface directories.
|
|
42
29
|
*/
|
|
43
30
|
export const STANDARD_IGNORE_PATTERNS = [
|
|
44
31
|
"dist",
|
|
@@ -53,10 +40,11 @@ export const STANDARD_IGNORE_PATTERNS = [
|
|
|
53
40
|
".opencode",
|
|
54
41
|
".runtime",
|
|
55
42
|
];
|
|
43
|
+
/** Rule map from agent-config SSOT (error severity for inject). */
|
|
44
|
+
export const rules = agentConfigRules;
|
|
56
45
|
/**
|
|
57
46
|
* 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.
|
|
47
|
+
* the build-time generator serializes this return value verbatim.
|
|
60
48
|
*/
|
|
61
49
|
export function buildOxlintrc() {
|
|
62
50
|
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)
|
|
@@ -12,6 +12,10 @@ import { loadContent } from "./loader.js";
|
|
|
12
12
|
const CONSUMER_DIR_BY_KIND = {
|
|
13
13
|
rule: "agent-rules",
|
|
14
14
|
skill: "agent-skills",
|
|
15
|
+
// Not reachable today (no `wp agent` CRUD command dispatches here), kept
|
|
16
|
+
// only to satisfy Record<ContentKind, string> exhaustiveness now that
|
|
17
|
+
// "agent" is a ContentKind for the unified-sync projection pipeline.
|
|
18
|
+
agent: "agent-agents",
|
|
15
19
|
};
|
|
16
20
|
function todayIsoDate() {
|
|
17
21
|
return new Date().toISOString().slice(0, 10);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* gray-matter object in both `rawFrontmatter` and `parsedFrontmatter` so the
|
|
15
15
|
* shape stays stable for downstream callers writing tests against it.
|
|
16
16
|
*/
|
|
17
|
-
export type ContentKind = "rule" | "skill";
|
|
17
|
+
export type ContentKind = "rule" | "skill" | "agent";
|
|
18
18
|
export type ContentSource = "canonical" | "consumer";
|
|
19
19
|
/**
|
|
20
20
|
* Stub raw frontmatter type. Replaced with schema output in Task 2.x.
|
|
@@ -21,10 +21,12 @@ const DEFAULT_KINDS = ["rule", "skill"];
|
|
|
21
21
|
const CONSUMER_DIR_BY_KIND = {
|
|
22
22
|
rule: "agent-rules",
|
|
23
23
|
skill: "agent-skills",
|
|
24
|
+
agent: "agent-agents",
|
|
24
25
|
};
|
|
25
26
|
const CATALOG_DIR_BY_KIND = {
|
|
26
27
|
rule: "rules",
|
|
27
28
|
skill: "skills",
|
|
29
|
+
agent: "agents",
|
|
28
30
|
};
|
|
29
31
|
export function loadContent(options) {
|
|
30
32
|
const { catalogDir, consumerRoot, kinds = DEFAULT_KINDS } = options;
|
|
@@ -83,9 +85,11 @@ function readKind(args) {
|
|
|
83
85
|
const stat = statSync(root);
|
|
84
86
|
if (!stat.isDirectory())
|
|
85
87
|
return [];
|
|
86
|
-
|
|
88
|
+
// agent kind shares the rule shape: flat `<slug>.md` files, README.md
|
|
89
|
+
// excluded. Only `skill` is directory-shaped (`<slug>/SKILL.md`).
|
|
90
|
+
return kind === "skill" ? readSkills(root, source) : readFlatMarkdown(kind, root, source);
|
|
87
91
|
}
|
|
88
|
-
function
|
|
92
|
+
function readFlatMarkdown(kind, root, source) {
|
|
89
93
|
const out = [];
|
|
90
94
|
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
91
95
|
if (!entry.isFile())
|
|
@@ -93,9 +97,9 @@ function readRules(root, source) {
|
|
|
93
97
|
if (!entry.name.endsWith(".md"))
|
|
94
98
|
continue;
|
|
95
99
|
// Skip directory-documentation files. README.md exists in both the
|
|
96
|
-
// canonical catalog and the consumer-owned agent-rules/
|
|
97
|
-
// surface; treating it as
|
|
98
|
-
// collision and would also try to project it into per-IDE surfaces.
|
|
100
|
+
// canonical catalog and the consumer-owned agent-rules/ (or agent-agents/)
|
|
101
|
+
// scaffolder surface; treating it as content would produce a spurious
|
|
102
|
+
// slug collision and would also try to project it into per-IDE surfaces.
|
|
99
103
|
if (entry.name === "README.md")
|
|
100
104
|
continue;
|
|
101
105
|
const filePath = realpathSync(join(root, entry.name));
|
|
@@ -103,7 +107,7 @@ function readRules(root, source) {
|
|
|
103
107
|
const parsed = matter(readFileSync(filePath, "utf8"));
|
|
104
108
|
const raw = { ...parsed.data };
|
|
105
109
|
out.push({
|
|
106
|
-
kind
|
|
110
|
+
kind,
|
|
107
111
|
slug,
|
|
108
112
|
source,
|
|
109
113
|
filePath,
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
export declare const DEFAULT_PACKAGED_SKILL_SLUGS: readonly ["verify", "fix", "investigate", "ai-deslop", "plan-refine", "ralplan", "best-practice-research", "testing-philosophy", "tph", "claude", "codex", "grok", "opencode-go", "plan-eng-review", "plan-ceo-review", "plan-design-review", "plan-devex-review", "browse", "devex-review", "design-review", "hooks-doctor", "tech-debt", "lore-protocol", "deep-interview", "deep-research", "autoresearch", "ultragoal", "autopilot", "team"];
|
|
2
2
|
export type DefaultPackagedSkillSlug = (typeof DEFAULT_PACKAGED_SKILL_SLUGS)[number];
|
|
3
3
|
export declare const DEFAULT_PACKAGED_SKILL_SLUG_SET: ReadonlySet<string>;
|
|
4
|
+
/**
|
|
5
|
+
* Catalog skills that are deliberately NOT in DEFAULT_PACKAGED_SKILL_SLUGS,
|
|
6
|
+
* with a one-line reason each. Every slug under `catalog/agent/skills/` must
|
|
7
|
+
* appear in either that list or this one (enforced by
|
|
8
|
+
* `checkCatalogSkillClassification` in `src/audit/agents.ts`) — an
|
|
9
|
+
* unclassified slug means a new catalog skill shipped without a deliberate
|
|
10
|
+
* packaging decision.
|
|
11
|
+
*/
|
|
12
|
+
export declare const UNPACKAGED_SKILL_SLUGS: Readonly<Record<string, string>>;
|
|
13
|
+
export declare const UNPACKAGED_SKILL_SLUG_SET: ReadonlySet<string>;
|
|
14
|
+
export declare function isUnpackagedSkillSlug(slug: string): boolean;
|
|
4
15
|
export declare const MERGED_DELETED_SKILL_SLUGS: readonly ["autoplan", "health", "systematic-debugging", "test-driven-development"];
|
|
5
16
|
export declare const MERGED_DELETED_SKILL_SLUG_SET: ReadonlySet<string>;
|
|
6
17
|
/**
|
|
@@ -30,6 +30,39 @@ export const DEFAULT_PACKAGED_SKILL_SLUGS = [
|
|
|
30
30
|
"team",
|
|
31
31
|
];
|
|
32
32
|
export const DEFAULT_PACKAGED_SKILL_SLUG_SET = new Set(DEFAULT_PACKAGED_SKILL_SLUGS);
|
|
33
|
+
/**
|
|
34
|
+
* Catalog skills that are deliberately NOT in DEFAULT_PACKAGED_SKILL_SLUGS,
|
|
35
|
+
* with a one-line reason each. Every slug under `catalog/agent/skills/` must
|
|
36
|
+
* appear in either that list or this one (enforced by
|
|
37
|
+
* `checkCatalogSkillClassification` in `src/audit/agents.ts`) — an
|
|
38
|
+
* unclassified slug means a new catalog skill shipped without a deliberate
|
|
39
|
+
* packaging decision.
|
|
40
|
+
*/
|
|
41
|
+
export const UNPACKAGED_SKILL_SLUGS = {
|
|
42
|
+
qa: "source-catalog QA skill, not package-visible in the default plugin skill set today (see workflow-skills-routing.md)",
|
|
43
|
+
"qa-only": "source-catalog QA skill, not package-visible in the default plugin skill set today (see workflow-skills-routing.md)",
|
|
44
|
+
review: "listed as a default workflow skill in workflow-skills-routing.md but not yet added to DEFAULT_PACKAGED_SKILL_SLUGS",
|
|
45
|
+
pll: "ultragoal's parallel-execute companion (ready-queue/worktrees driver); not independently default-packaged",
|
|
46
|
+
"frontend-design": "opt-in design-guidance skill, not part of the default packaged workflow set",
|
|
47
|
+
"monorepo-navigation": "tier-3 opt-in preset (wp setup --with monorepo-navigation), not default-packaged",
|
|
48
|
+
"tanstack-query": "tier-3 opt-in preset (wp setup --with tanstack-query), not default-packaged",
|
|
49
|
+
"react-doctor": "opt-in framework best-practice skill, not default-packaged",
|
|
50
|
+
"better-auth-best-practices": "opt-in best-practice reference skill, not default-packaged",
|
|
51
|
+
"logging-best-practices": "opt-in best-practice reference skill, not default-packaged",
|
|
52
|
+
"vercel-react-best-practices": "opt-in best-practice reference skill, not default-packaged",
|
|
53
|
+
"web-design-guidelines": "opt-in best-practice reference skill, not default-packaged",
|
|
54
|
+
deepseek: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
55
|
+
glm: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
56
|
+
hy3: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
57
|
+
kimi: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
58
|
+
mimo: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
59
|
+
minimax: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
60
|
+
qwen: "individual OpenCode-Go model reviewer skill; only the aggregate opencode-go skill is default-packaged",
|
|
61
|
+
};
|
|
62
|
+
export const UNPACKAGED_SKILL_SLUG_SET = new Set(Object.keys(UNPACKAGED_SKILL_SLUGS));
|
|
63
|
+
export function isUnpackagedSkillSlug(slug) {
|
|
64
|
+
return UNPACKAGED_SKILL_SLUG_SET.has(slug);
|
|
65
|
+
}
|
|
33
66
|
export const MERGED_DELETED_SKILL_SLUGS = [
|
|
34
67
|
"autoplan",
|
|
35
68
|
"health",
|