@danieljvdm/dev-kit 0.16.0 → 0.18.0
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 +18 -7
- package/package.json +20 -9
- package/scripts/sync-anti-slop-runtime.mjs +19 -0
- package/skill-sources.jsonc +17 -0
- package/skill-sources.lock.json +48 -0
- package/skills/dev-kit/SKILL.md +4 -5
- package/src/bin/dev-kit.ts +11 -7
- package/src/catalog-manager.ts +23 -18
- package/src/catalog.ts +8 -5
- package/src/cli-ui.ts +2 -2
- package/src/effect-tsgo.ts +10 -6
- package/src/gitignore.ts +6 -3
- package/src/manifest.ts +10 -2
- package/src/oxlint-plugin-anti-slop/LICENSE +21 -0
- package/src/oxlint-plugin-anti-slop/index.ts +43 -0
- package/src/oxlint-plugin-anti-slop/rules/no-chained-type-assertions.ts +79 -0
- package/src/oxlint-plugin-anti-slop/rules/no-conditional-empty-object-spread.ts +51 -0
- package/src/oxlint-plugin-anti-slop/rules/no-known-value-widening.ts +267 -0
- package/src/oxlint-plugin-anti-slop/rules/no-module-mocking.ts +105 -0
- package/src/oxlint-plugin-anti-slop/rules/no-object-parameters.ts +141 -0
- package/src/oxlint-plugin-anti-slop/rules/no-reflect-apply.ts +28 -0
- package/src/oxlint-plugin-anti-slop/rules/no-reflect-get.ts +28 -0
- package/src/oxlint-plugin-anti-slop/rules/no-runtime-typeof.ts +25 -0
- package/src/oxlint-plugin-anti-slop/rules/no-shape-in-symbol-names.ts +38 -0
- package/src/oxlint-plugin-anti-slop/rules/no-unknown-parameters.ts +86 -0
- package/src/oxlint-plugin-anti-slop/rules/no-unknown-returns.ts +125 -0
- package/src/oxlint-plugin-anti-slop/rules/no-unknown-type-aliases.ts +73 -0
- package/src/oxlint-plugin-anti-slop/rules/no-unsafe-dictionary-type.ts +139 -0
- package/src/oxlint-plugin-anti-slop/rules/no-widen-then-assert.ts +396 -0
- package/src/oxlint-plugin-anti-slop/rules/require-safety-comment-for-type-assertion.ts +61 -0
- package/src/oxlint-plugin-anti-slop/runtime.d.ts +22 -0
- package/src/oxlint-plugin-anti-slop/runtime.js +1209 -0
- package/src/oxlint-plugin-anti-slop/shared/dictionary-types.ts +555 -0
- package/src/oxlint-plugin-anti-slop/shared/reflect-method.ts +40 -0
- package/src/oxlint-plugin-effect.d.ts +4 -2
- package/src/oxlint.js +19 -0
- package/src/oxlint.ts +22 -5
- package/src/package-skill-source.ts +17 -25
- package/src/path-digest.ts +2 -1
- package/src/project-package.ts +14 -12
- package/src/skill-manager.ts +25 -13
- package/src/sync.ts +65 -49
- package/src/vendor.ts +35 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, FileSystem, Path, Result, Schema } from "effect";
|
|
1
|
+
import { Effect, FileSystem, Option, Path, Result, Schema } from "effect";
|
|
2
2
|
|
|
3
3
|
import { observeSymbolicLink } from "./node-symbolic-link.ts";
|
|
4
4
|
import { readDirectDependencyNames } from "./project-package.ts";
|
|
@@ -34,33 +34,25 @@ const PackageMetadataSchema = Schema.fromJsonString(
|
|
|
34
34
|
}),
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const DiscoveryLocationSchema = Schema.String.check(Schema.isPattern(/\S/));
|
|
38
|
+
const IntentDiscoveryMetadataSchema = Schema.Struct({
|
|
39
|
+
version: Schema.Literal(1),
|
|
40
|
+
repo: DiscoveryLocationSchema,
|
|
41
|
+
docs: DiscoveryLocationSchema,
|
|
42
|
+
});
|
|
43
|
+
const RepositoryDiscoveryMetadataSchema = Schema.Union([
|
|
44
|
+
DiscoveryLocationSchema,
|
|
45
|
+
Schema.Struct({ url: DiscoveryLocationSchema }),
|
|
46
|
+
]);
|
|
47
|
+
const decodeIntentDiscoveryMetadata = Schema.decodeUnknownOption(IntentDiscoveryMetadataSchema);
|
|
48
|
+
const decodeRepositoryDiscoveryMetadata = Schema.decodeUnknownOption(
|
|
49
|
+
RepositoryDiscoveryMetadataSchema,
|
|
50
|
+
);
|
|
39
51
|
|
|
40
52
|
const hasIntentDiscoveryMetadata = (metadata: typeof PackageMetadataSchema.Type): boolean => {
|
|
41
|
-
|
|
53
|
+
if (Option.isSome(decodeIntentDiscoveryMetadata(metadata.intent))) return true;
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
typeof intent === "object" &&
|
|
45
|
-
intent !== null &&
|
|
46
|
-
"version" in intent &&
|
|
47
|
-
intent.version === 1 &&
|
|
48
|
-
"repo" in intent &&
|
|
49
|
-
nonEmptyString(intent.repo) &&
|
|
50
|
-
"docs" in intent &&
|
|
51
|
-
nonEmptyString(intent.docs)
|
|
52
|
-
) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
const repository = metadata.repository;
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
nonEmptyString(repository) ||
|
|
59
|
-
(typeof repository === "object" &&
|
|
60
|
-
repository !== null &&
|
|
61
|
-
"url" in repository &&
|
|
62
|
-
nonEmptyString(repository.url))
|
|
63
|
-
);
|
|
55
|
+
return Option.isSome(decodeRepositoryDiscoveryMetadata(metadata.repository));
|
|
64
56
|
};
|
|
65
57
|
|
|
66
58
|
const isSafePackageVersion = (value: string): boolean =>
|
package/src/path-digest.ts
CHANGED
|
@@ -23,13 +23,14 @@ export class PathInspectionError extends Schema.TaggedError<PathInspectionError>
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const textEncoder = new TextEncoder();
|
|
26
|
+
const isString = Schema.is(Schema.String);
|
|
26
27
|
|
|
27
28
|
// Git preserves only the executable distinction for regular files. Canonicalizing
|
|
28
29
|
// the remaining bits keeps digests stable across checkout and copy umasks.
|
|
29
30
|
const canonicalFileMode = (mode: number): number => ((mode & 0o111) === 0 ? 0o644 : 0o755);
|
|
30
31
|
|
|
31
32
|
const frame = (value: string | Uint8Array): Uint8Array => {
|
|
32
|
-
const bytes =
|
|
33
|
+
const bytes = isString(value) ? textEncoder.encode(value) : value;
|
|
33
34
|
const framed = new Uint8Array(4 + bytes.length);
|
|
34
35
|
|
|
35
36
|
new DataView(framed.buffer).setUint32(0, bytes.length);
|
package/src/project-package.ts
CHANGED
|
@@ -47,14 +47,16 @@ export const PACKAGE_MANAGER_COMMANDS = {
|
|
|
47
47
|
yarn: { install: "yarn install", label: "Yarn" },
|
|
48
48
|
} as const;
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
const PackageManagerNameSchema = Schema.Literals(["bun", "npm", "pnpm", "yarn"]);
|
|
51
|
+
|
|
52
|
+
export type PackageManagerName = typeof PackageManagerNameSchema.Type;
|
|
53
|
+
|
|
54
|
+
const decodePackageManagerName = Schema.decodeUnknownOption(PackageManagerNameSchema);
|
|
51
55
|
|
|
52
56
|
const packageManagerName = (declaration: string | undefined): PackageManagerName | undefined => {
|
|
53
57
|
const name = declaration?.split("@", 1)[0];
|
|
54
58
|
|
|
55
|
-
return name
|
|
56
|
-
? (name as PackageManagerName)
|
|
57
|
-
: undefined;
|
|
59
|
+
return name === undefined ? undefined : Option.getOrUndefined(decodePackageManagerName(name));
|
|
58
60
|
};
|
|
59
61
|
|
|
60
62
|
export const detectPackageManager = Effect.fn("detectPackageManager")(function* (
|
|
@@ -129,13 +131,9 @@ const WorkspacePatternsSchema = Schema.Union([
|
|
|
129
131
|
// this is a genuinely untyped boundary.
|
|
130
132
|
const decodeWorkspacePatterns = Schema.decodeUnknownOption(WorkspacePatternsSchema);
|
|
131
133
|
|
|
132
|
-
const workspacePatterns = (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (Option.isNone(decoded)) return [];
|
|
136
|
-
|
|
137
|
-
return "packages" in decoded.value ? decoded.value.packages : decoded.value;
|
|
138
|
-
};
|
|
134
|
+
const workspacePatterns = (
|
|
135
|
+
workspaces: typeof WorkspacePatternsSchema.Type,
|
|
136
|
+
): ReadonlyArray<string> => ("packages" in workspaces ? workspaces.packages : workspaces);
|
|
139
137
|
|
|
140
138
|
/**
|
|
141
139
|
* Direct dependency names of the project package plus every workspace member
|
|
@@ -149,8 +147,12 @@ export const readWorkspaceDependencyNames = Effect.fn("readWorkspaceDependencyNa
|
|
|
149
147
|
const path = yield* Path.Path;
|
|
150
148
|
const manifest = yield* readOptionalProjectPackage(projectDir);
|
|
151
149
|
const names = new Set(manifestDependencyNames(manifest));
|
|
150
|
+
const decodedWorkspaces = decodeWorkspacePatterns(manifest?.workspaces);
|
|
151
|
+
const patterns = Option.isSome(decodedWorkspaces)
|
|
152
|
+
? workspacePatterns(decodedWorkspaces.value)
|
|
153
|
+
: [];
|
|
152
154
|
|
|
153
|
-
for (const pattern of
|
|
155
|
+
for (const pattern of patterns) {
|
|
154
156
|
if (pattern.startsWith("!")) continue;
|
|
155
157
|
const star = pattern.indexOf("*");
|
|
156
158
|
let memberDirs: ReadonlyArray<string> = [];
|
package/src/skill-manager.ts
CHANGED
|
@@ -19,6 +19,11 @@ type ManagerOptions = {
|
|
|
19
19
|
readonly apply?: boolean;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type ManagerSyncOptions = {
|
|
23
|
+
projectDir?: string;
|
|
24
|
+
manifestPath?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
22
27
|
const packageRoot = Effect.fn("skillManagerPackageRoot")(function* () {
|
|
23
28
|
const path = yield* Path.Path;
|
|
24
29
|
|
|
@@ -150,6 +155,11 @@ const readManifest = Effect.fn("readManagedSkillManifest")(function* (
|
|
|
150
155
|
return { ...paths, manifest, raw };
|
|
151
156
|
});
|
|
152
157
|
|
|
158
|
+
const ManifestSelectionSchema = Schema.Struct({
|
|
159
|
+
include: Schema.optional(Schema.Array(Schema.String)),
|
|
160
|
+
exclude: Schema.optional(Schema.Array(Schema.String)),
|
|
161
|
+
});
|
|
162
|
+
|
|
153
163
|
const writeArray = Effect.fn("writeManifestArray")(function* (
|
|
154
164
|
manifestPath: string,
|
|
155
165
|
raw: string,
|
|
@@ -157,12 +167,10 @@ const writeArray = Effect.fn("writeManifestArray")(function* (
|
|
|
157
167
|
values: ReadonlyArray<string>,
|
|
158
168
|
) {
|
|
159
169
|
const fs = yield* FileSystem.FileSystem;
|
|
160
|
-
const parsed = parseJsonc(raw)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
)
|
|
165
|
-
: undefined;
|
|
170
|
+
const parsed = yield* Schema.decodeUnknownEffect(ManifestSelectionSchema)(parseJsonc(raw)).pipe(
|
|
171
|
+
Effect.mapError((error) => SkillManagerError.make({ message: error.message })),
|
|
172
|
+
);
|
|
173
|
+
const current = parsed[property];
|
|
166
174
|
|
|
167
175
|
if (current === undefined) {
|
|
168
176
|
if (values.length === 0) return;
|
|
@@ -239,13 +247,17 @@ const summary = (description: string, defaultDescription: string): string => {
|
|
|
239
247
|
return firstSentence.length > 96 ? `${firstSentence.slice(0, 93).trimEnd()}…` : firstSentence;
|
|
240
248
|
};
|
|
241
249
|
|
|
242
|
-
const applyIfRequested = (options: ManagerOptions) =>
|
|
243
|
-
options.apply === false
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
250
|
+
const applyIfRequested = (options: ManagerOptions) => {
|
|
251
|
+
if (options.apply === false) {
|
|
252
|
+
return printStatus("success", "Manifest updated", "run dev-kit sync to apply");
|
|
253
|
+
}
|
|
254
|
+
const syncOptions: ManagerSyncOptions = {};
|
|
255
|
+
|
|
256
|
+
if (options.projectDir !== undefined) syncOptions.projectDir = options.projectDir;
|
|
257
|
+
if (options.manifestPath !== undefined) syncOptions.manifestPath = options.manifestPath;
|
|
258
|
+
|
|
259
|
+
return runProjectSkillPlan(syncOptions);
|
|
260
|
+
};
|
|
249
261
|
|
|
250
262
|
export const initProject = Effect.fn("initDevKitProject")(function* (options: ManagerOptions) {
|
|
251
263
|
const fs = yield* FileSystem.FileSystem;
|
package/src/sync.ts
CHANGED
|
@@ -267,7 +267,7 @@ const encodeOutputOwnershipIdentityJson = Schema.encodeSync(
|
|
|
267
267
|
const encodePlanSnapshotJson = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown));
|
|
268
268
|
const encodeAppliedStatePrettyJson = Schema.encodeSync(fromJsonString(AppliedStateSchema, 2));
|
|
269
269
|
|
|
270
|
-
const SKILL_FAMILIES
|
|
270
|
+
const SKILL_FAMILIES = {
|
|
271
271
|
effect: [
|
|
272
272
|
"effect-ts",
|
|
273
273
|
"effect-architecture-audit",
|
|
@@ -275,7 +275,7 @@ const SKILL_FAMILIES: SkillCatalog = {
|
|
|
275
275
|
"effect-atom-state",
|
|
276
276
|
"build-effect-clis",
|
|
277
277
|
],
|
|
278
|
-
};
|
|
278
|
+
} satisfies SkillCatalog;
|
|
279
279
|
|
|
280
280
|
export const DEFAULT_MANIFEST = "dev-kit.jsonc";
|
|
281
281
|
const DEFAULT_LOCKFILE = "dev-kit.lock.json";
|
|
@@ -356,12 +356,12 @@ const inspectManagedInstructionSections = (content: string): ManagedInstructionI
|
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
+
if (ranges.length === 0) return { kind: "valid", ranges };
|
|
360
|
+
|
|
359
361
|
return {
|
|
360
362
|
kind: "valid",
|
|
361
363
|
ranges,
|
|
362
|
-
|
|
363
|
-
? {}
|
|
364
|
-
: { content: `${ranges.map((range) => range.content.trim()).join("\n\n")}\n` }),
|
|
364
|
+
content: `${ranges.map((range) => range.content.trim()).join("\n\n")}\n`,
|
|
365
365
|
};
|
|
366
366
|
};
|
|
367
367
|
|
|
@@ -460,6 +460,8 @@ const renderPackageScriptCommandPolicy = (
|
|
|
460
460
|
const additionalCommands = Object.keys(scripts)
|
|
461
461
|
.filter(
|
|
462
462
|
(script) =>
|
|
463
|
+
// SAFETY: `script` is only asserted to the set's string-literal union for a
|
|
464
|
+
// runtime membership check; the assertion does not narrow any returned value.
|
|
463
465
|
!knownScripts.has(script as (typeof entries)[number][0]) &&
|
|
464
466
|
/^(?:check|validate|fmt|format|lint|test|type-?check)(?::|$)/.test(script),
|
|
465
467
|
)
|
|
@@ -955,7 +957,7 @@ const buildDesiredOutputs = Effect.fn("buildDesiredSkillOutputs")(function* (
|
|
|
955
957
|
const managed = yield* resolveManagedPath(projectDir, path.join(target.path, skill.name));
|
|
956
958
|
|
|
957
959
|
if (target.mode === "copy") {
|
|
958
|
-
|
|
960
|
+
const output: DesiredSkillOutput = {
|
|
959
961
|
resourceId: `skill:${skill.selector}@${targetName}`,
|
|
960
962
|
path: managed.relative,
|
|
961
963
|
skill: skill.name,
|
|
@@ -963,10 +965,12 @@ const buildDesiredOutputs = Effect.fn("buildDesiredSkillOutputs")(function* (
|
|
|
963
965
|
mode: "copy",
|
|
964
966
|
kind: "directory",
|
|
965
967
|
digest: sourceObservation.digest,
|
|
966
|
-
...(resolvedSource.catalog ? { catalog: resolvedSource.catalog } : {}),
|
|
967
968
|
source,
|
|
968
969
|
destination: managed.absolute,
|
|
969
|
-
}
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
if (resolvedSource.catalog) Object.assign(output, { catalog: resolvedSource.catalog });
|
|
973
|
+
outputs.push(output);
|
|
970
974
|
continue;
|
|
971
975
|
}
|
|
972
976
|
const linkSource =
|
|
@@ -977,7 +981,7 @@ const buildDesiredOutputs = Effect.fn("buildDesiredSkillOutputs")(function* (
|
|
|
977
981
|
const linkTarget = path.relative(path.dirname(managed.absolute), linkSource);
|
|
978
982
|
const linkDigest = yield* digestSymlinkTarget(linkTarget);
|
|
979
983
|
|
|
980
|
-
|
|
984
|
+
const output: DesiredSkillOutput = {
|
|
981
985
|
resourceId: `skill:${skill.selector}@${targetName}`,
|
|
982
986
|
path: managed.relative,
|
|
983
987
|
skill: skill.name,
|
|
@@ -985,11 +989,13 @@ const buildDesiredOutputs = Effect.fn("buildDesiredSkillOutputs")(function* (
|
|
|
985
989
|
mode: "symlink",
|
|
986
990
|
kind: "symlink",
|
|
987
991
|
digest: linkDigest,
|
|
988
|
-
...(resolvedSource.catalog ? { catalog: resolvedSource.catalog } : {}),
|
|
989
992
|
source,
|
|
990
993
|
destination: managed.absolute,
|
|
991
994
|
linkTarget,
|
|
992
|
-
}
|
|
995
|
+
};
|
|
996
|
+
|
|
997
|
+
if (resolvedSource.catalog) Object.assign(output, { catalog: resolvedSource.catalog });
|
|
998
|
+
outputs.push(output);
|
|
993
999
|
}
|
|
994
1000
|
}
|
|
995
1001
|
yield* validateInventory(projectDir, outputs, "desired outputs");
|
|
@@ -1175,14 +1181,15 @@ const planDesiredOutputs = Effect.fn("planDesiredSkillOutputs")(function* (
|
|
|
1175
1181
|
|
|
1176
1182
|
if (managedDigest === receipt.digest || observed.digest === receipt.digest) {
|
|
1177
1183
|
const remaining = removeManagedInstructionSections(existingContent, inspection.ranges);
|
|
1178
|
-
|
|
1179
|
-
actions.push({
|
|
1184
|
+
const action: SkillPlanAction = {
|
|
1180
1185
|
action: "remove",
|
|
1181
1186
|
previous: receipt,
|
|
1182
1187
|
destination: managed.absolute,
|
|
1183
1188
|
observed,
|
|
1184
|
-
|
|
1185
|
-
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
if (remaining.trim().length > 0) Object.assign(action, { stagedContent: remaining });
|
|
1192
|
+
actions.push(action);
|
|
1186
1193
|
} else {
|
|
1187
1194
|
actions.push({
|
|
1188
1195
|
action: "conflict",
|
|
@@ -1363,35 +1370,36 @@ export const planProjectSkills = Effect.fn("planProjectSkills")(function* (optio
|
|
|
1363
1370
|
manifest.setup,
|
|
1364
1371
|
manifest.targets,
|
|
1365
1372
|
);
|
|
1373
|
+
const nextSetup: NonNullable<DevKitLock["setup"]> = {};
|
|
1374
|
+
|
|
1375
|
+
if (effectSource !== undefined) {
|
|
1376
|
+
Object.assign(nextSetup, {
|
|
1377
|
+
effectSource: {
|
|
1378
|
+
packageName: effectSource.packageName,
|
|
1379
|
+
packageVersion: effectSource.packageVersion,
|
|
1380
|
+
path: effectSource.path,
|
|
1381
|
+
repository: effectSource.repository,
|
|
1382
|
+
tag: effectSource.tag,
|
|
1383
|
+
},
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
if (effectTsgo !== undefined) {
|
|
1387
|
+
Object.assign(nextSetup, {
|
|
1388
|
+
effectTsgo: {
|
|
1389
|
+
effectTsgoVersion: effectTsgo.effectTsgoVersion,
|
|
1390
|
+
typescriptPackage: effectTsgo.typescriptPackage,
|
|
1391
|
+
typescriptVersion: effectTsgo.typescriptVersion,
|
|
1392
|
+
},
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1366
1395
|
const nextLock: DevKitLock = {
|
|
1367
1396
|
version: 1,
|
|
1368
1397
|
toolVersion: DEV_KIT_VERSION,
|
|
1369
1398
|
manifestDigest: yield* digestText(encodeManifestJson(manifest)),
|
|
1370
|
-
setup:
|
|
1371
|
-
...(effectSource === undefined
|
|
1372
|
-
? {}
|
|
1373
|
-
: {
|
|
1374
|
-
effectSource: {
|
|
1375
|
-
packageName: effectSource.packageName,
|
|
1376
|
-
packageVersion: effectSource.packageVersion,
|
|
1377
|
-
path: effectSource.path,
|
|
1378
|
-
repository: effectSource.repository,
|
|
1379
|
-
tag: effectSource.tag,
|
|
1380
|
-
},
|
|
1381
|
-
}),
|
|
1382
|
-
...(effectTsgo === undefined
|
|
1383
|
-
? {}
|
|
1384
|
-
: {
|
|
1385
|
-
effectTsgo: {
|
|
1386
|
-
effectTsgoVersion: effectTsgo.effectTsgoVersion,
|
|
1387
|
-
typescriptPackage: effectTsgo.typescriptPackage,
|
|
1388
|
-
typescriptVersion: effectTsgo.typescriptVersion,
|
|
1389
|
-
},
|
|
1390
|
-
}),
|
|
1391
|
-
},
|
|
1399
|
+
setup: nextSetup,
|
|
1392
1400
|
outputs: desired.map((output): ManagedOutput => {
|
|
1393
1401
|
if ("skill" in output) {
|
|
1394
|
-
|
|
1402
|
+
const managedOutput: ManagedSkillOutput = {
|
|
1395
1403
|
resourceId: output.resourceId,
|
|
1396
1404
|
path: output.path,
|
|
1397
1405
|
skill: output.skill,
|
|
@@ -1399,8 +1407,11 @@ export const planProjectSkills = Effect.fn("planProjectSkills")(function* (optio
|
|
|
1399
1407
|
mode: output.mode,
|
|
1400
1408
|
kind: output.kind,
|
|
1401
1409
|
digest: output.digest,
|
|
1402
|
-
...(output.catalog ? { catalog: output.catalog } : {}),
|
|
1403
1410
|
};
|
|
1411
|
+
|
|
1412
|
+
if (output.catalog) Object.assign(managedOutput, { catalog: output.catalog });
|
|
1413
|
+
|
|
1414
|
+
return managedOutput;
|
|
1404
1415
|
}
|
|
1405
1416
|
if (output.resourceId === "setup:agent-instructions") {
|
|
1406
1417
|
return {
|
|
@@ -1488,16 +1499,11 @@ export const planProjectSkills = Effect.fn("planProjectSkills")(function* (optio
|
|
|
1488
1499
|
});
|
|
1489
1500
|
}
|
|
1490
1501
|
|
|
1491
|
-
|
|
1502
|
+
const plan: SkillPlan = {
|
|
1492
1503
|
projectDir,
|
|
1493
1504
|
lockfilePath: lockManaged.absolute,
|
|
1494
1505
|
statePath: stateManaged.absolute,
|
|
1495
1506
|
actions: planned.actions,
|
|
1496
|
-
...(effectSource === undefined ? {} : { effectSource }),
|
|
1497
|
-
...(effectTsgo === undefined ? {} : { effectTsgo }),
|
|
1498
|
-
...(vitePlusHooks === undefined ? {} : { vitePlusHooks }),
|
|
1499
|
-
...(vitePlusWorkflow === undefined ? {} : { vitePlusWorkflow }),
|
|
1500
|
-
...(worktrunkConfig === undefined ? {} : { worktrunkConfig }),
|
|
1501
1507
|
nextLock,
|
|
1502
1508
|
nextState: planned.nextState,
|
|
1503
1509
|
metadataChanged:
|
|
@@ -1505,7 +1511,15 @@ export const planProjectSkills = Effect.fn("planProjectSkills")(function* (optio
|
|
|
1505
1511
|
encodeDevKitLockJson(currentLock) !== encodeDevKitLockJson(nextLock) ||
|
|
1506
1512
|
currentState === undefined ||
|
|
1507
1513
|
encodeAppliedStateJson(currentState) !== encodeAppliedStateJson(planned.nextState),
|
|
1508
|
-
}
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
if (effectSource !== undefined) Object.assign(plan, { effectSource });
|
|
1517
|
+
if (effectTsgo !== undefined) Object.assign(plan, { effectTsgo });
|
|
1518
|
+
if (vitePlusHooks !== undefined) Object.assign(plan, { vitePlusHooks });
|
|
1519
|
+
if (vitePlusWorkflow !== undefined) Object.assign(plan, { vitePlusWorkflow });
|
|
1520
|
+
if (worktrunkConfig !== undefined) Object.assign(plan, { worktrunkConfig });
|
|
1521
|
+
|
|
1522
|
+
return plan;
|
|
1509
1523
|
});
|
|
1510
1524
|
|
|
1511
1525
|
const formatAction = (action: SkillPlanAction): string => {
|
|
@@ -1761,13 +1775,15 @@ const applyPlannedSkillChanges = Effect.fn("applyPlannedSkillChanges")(function*
|
|
|
1761
1775
|
}`,
|
|
1762
1776
|
});
|
|
1763
1777
|
}
|
|
1764
|
-
|
|
1778
|
+
const replacement: Replacement = {
|
|
1765
1779
|
destination: action.action === "remove" ? action.destination : action.desired.destination,
|
|
1766
1780
|
backup: path.join(backupDir, String(replacementIndex++)),
|
|
1767
1781
|
expected: action.observed,
|
|
1768
1782
|
path: action.action === "remove" ? action.previous.path : action.desired.path,
|
|
1769
|
-
|
|
1770
|
-
|
|
1783
|
+
};
|
|
1784
|
+
|
|
1785
|
+
if (staged !== undefined) Object.assign(replacement, { staged });
|
|
1786
|
+
replacements.push(replacement);
|
|
1771
1787
|
}
|
|
1772
1788
|
replacements.push(
|
|
1773
1789
|
{
|
package/src/vendor.ts
CHANGED
|
@@ -158,11 +158,13 @@ const normalizeRepositoryLocator = (
|
|
|
158
158
|
const normalized = `https://github.com/${owner}/${name}.git`;
|
|
159
159
|
|
|
160
160
|
if (segments[2] === "tree" && segments[3]) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
161
|
+
const locator = { repository: normalized, ref: segments[3] };
|
|
162
|
+
|
|
163
|
+
if (segments.length > 4) {
|
|
164
|
+
Object.assign(locator, { skillsPath: segments.slice(4).join("/") });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return Effect.succeed(locator);
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
return Effect.succeed({ repository: normalized });
|
|
@@ -493,13 +495,16 @@ const prepareSource = Effect.fn("prepareSkillSource")(function* (
|
|
|
493
495
|
}
|
|
494
496
|
}
|
|
495
497
|
|
|
496
|
-
|
|
498
|
+
const prepared = {
|
|
497
499
|
checkoutDir,
|
|
498
500
|
resolved,
|
|
499
501
|
skills,
|
|
500
502
|
source,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
if (licenseSource) Object.assign(prepared, { licenseSource });
|
|
506
|
+
|
|
507
|
+
return prepared satisfies PreparedSource;
|
|
503
508
|
});
|
|
504
509
|
|
|
505
510
|
const readCurrentLock = Effect.fn("readCurrentSkillSourcesLock")(function* (lockfilePath: string) {
|
|
@@ -713,20 +718,31 @@ const buildLock = Effect.fn("buildSkillCatalogLock")(function* (
|
|
|
713
718
|
}
|
|
714
719
|
digests[skill] = observation.digest;
|
|
715
720
|
}
|
|
716
|
-
|
|
721
|
+
const lockedSource = {
|
|
717
722
|
id: source.id,
|
|
718
723
|
repository: source.repository,
|
|
719
724
|
ref: source.ref,
|
|
720
725
|
resolved,
|
|
721
726
|
skillsPath: source.skillsPath,
|
|
722
727
|
include: source.include,
|
|
723
|
-
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
if (source.exclude) Object.assign(lockedSource, { exclude: source.exclude });
|
|
731
|
+
|
|
732
|
+
const completeLockedSource = Object.assign(lockedSource, {
|
|
724
733
|
skills,
|
|
725
734
|
descriptions,
|
|
726
735
|
digests,
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
736
|
+
}) satisfies LockedSkillSource;
|
|
737
|
+
|
|
738
|
+
if (source.licensePath) {
|
|
739
|
+
Object.assign(completeLockedSource, { licensePath: source.licensePath });
|
|
740
|
+
}
|
|
741
|
+
if (source.stripFrontmatter) {
|
|
742
|
+
Object.assign(completeLockedSource, { stripFrontmatter: source.stripFrontmatter });
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
sources.push(completeLockedSource);
|
|
730
746
|
}
|
|
731
747
|
|
|
732
748
|
return { version: 1, sources } satisfies SkillSourcesLock;
|
|
@@ -807,15 +823,18 @@ export const inspectCatalogRepository = Effect.fn("inspectCatalogRepository")(fu
|
|
|
807
823
|
}
|
|
808
824
|
}
|
|
809
825
|
|
|
810
|
-
|
|
826
|
+
const inspection: CatalogInspection = {
|
|
811
827
|
id,
|
|
812
828
|
repository,
|
|
813
829
|
ref,
|
|
814
830
|
resolved: prepared.resolved,
|
|
815
831
|
skillsPath: source.skillsPath,
|
|
816
832
|
skills,
|
|
817
|
-
|
|
818
|
-
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
if (licensePath) Object.assign(inspection, { licensePath });
|
|
836
|
+
|
|
837
|
+
return inspection;
|
|
819
838
|
});
|
|
820
839
|
|
|
821
840
|
export const refreshSkillCatalog = Effect.fn("refreshSkillCatalog")(function* (
|