skillset 0.13.4 → 0.13.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/dist/cli.js +569 -336
- package/dist/create.js +569 -336
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7024,7 +7024,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
7024
7024
|
});
|
|
7025
7025
|
|
|
7026
7026
|
// apps/skillset/src/cli-core.ts
|
|
7027
|
-
import { mkdir as
|
|
7027
|
+
import { mkdir as mkdir11, writeFile as writeFile11 } from "fs/promises";
|
|
7028
7028
|
import { basename as basename8, dirname as dirname15, resolve as resolve10 } from "path";
|
|
7029
7029
|
|
|
7030
7030
|
// packages/core/src/authoring.ts
|
|
@@ -7095,7 +7095,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7095
7095
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-112 activation probe coverage")],
|
|
7096
7096
|
id: "activation-probes",
|
|
7097
7097
|
kind: "workflow",
|
|
7098
|
-
|
|
7098
|
+
renderOwner: "apps/skillset/src/test-runner.ts",
|
|
7099
7099
|
sourceShape: ".skillset/config.yaml tests.<name>.activation[]",
|
|
7100
7100
|
status: "implemented",
|
|
7101
7101
|
summary: "Compiles target-aware manual activation probe assets inside isolated test runs.",
|
|
@@ -7108,7 +7108,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7108
7108
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-34/35/36 change status and entry coverage")],
|
|
7109
7109
|
id: "changes",
|
|
7110
7110
|
kind: "change-management",
|
|
7111
|
-
|
|
7111
|
+
renderOwner: "apps/skillset/src/change-entries.ts",
|
|
7112
7112
|
sourceShape: ".skillset/changes/pending/*.yaml and .skillset/changes/history/*.jsonl",
|
|
7113
7113
|
status: "implemented",
|
|
7114
7114
|
summary: "Tracks source-unit changes, evidence hashes, pending entries, and applied history.",
|
|
@@ -7118,13 +7118,13 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7118
7118
|
}),
|
|
7119
7119
|
feature({
|
|
7120
7120
|
docs: ["docs/features/dependencies.md"],
|
|
7121
|
-
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-40 dependency
|
|
7121
|
+
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-40 dependency rendering tests")],
|
|
7122
7122
|
id: "dependencies",
|
|
7123
7123
|
kind: "metadata",
|
|
7124
|
-
|
|
7124
|
+
renderOwner: "packages/core/src/dependencies.ts",
|
|
7125
7125
|
sourceShape: "plugin skillset.yaml dependencies",
|
|
7126
7126
|
status: "implemented",
|
|
7127
|
-
summary: "Declares plugin dependencies and
|
|
7127
|
+
summary: "Declares plugin dependencies and renders target-specific install/awareness behavior.",
|
|
7128
7128
|
targetSupport: {
|
|
7129
7129
|
claude: {
|
|
7130
7130
|
evidence: [docs("docs/features/dependencies.md"), externalDocs("https://docs.anthropic.com/en/docs/claude-code/plugins", "2026-06-12")],
|
|
@@ -7145,7 +7145,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7145
7145
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-109 distribute plan coverage")],
|
|
7146
7146
|
id: "distributions",
|
|
7147
7147
|
kind: "workflow",
|
|
7148
|
-
|
|
7148
|
+
renderOwner: "packages/core/src/distribution.ts",
|
|
7149
7149
|
sourceShape: ".skillset/config.yaml distributions",
|
|
7150
7150
|
status: "implemented",
|
|
7151
7151
|
summary: "Plans post-build distribution of generated projections without writing or activating runtimes.",
|
|
@@ -7164,36 +7164,36 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7164
7164
|
],
|
|
7165
7165
|
id: "feature-registry",
|
|
7166
7166
|
kind: "workflow",
|
|
7167
|
-
|
|
7167
|
+
renderOwner: "packages/core/src/feature-registry.ts",
|
|
7168
7168
|
sourceShape: "typed feature entries in packages/core/src/feature-registry.ts",
|
|
7169
7169
|
status: "implemented",
|
|
7170
|
-
summary: "Records feature ids, target capability claims, docs, evidence,
|
|
7170
|
+
summary: "Records feature ids, target capability claims, docs, evidence, render owners, and validation owners.",
|
|
7171
7171
|
targetSupport: notTargetRuntime(),
|
|
7172
7172
|
title: "Feature Registry",
|
|
7173
7173
|
validationOwner: "packages/core/src/feature-registry.ts"
|
|
7174
7174
|
}),
|
|
7175
7175
|
feature({
|
|
7176
|
-
docs: ["docs/features/
|
|
7176
|
+
docs: ["docs/features/render-results.md"],
|
|
7177
7177
|
evidence: [
|
|
7178
7178
|
docs("docs/adrs/drafts/20260614-lowering-outcomes-and-loss-ledger.md"),
|
|
7179
|
-
source("packages/core/src/
|
|
7180
|
-
source("packages/core/src/
|
|
7179
|
+
source("packages/core/src/render-result.ts"),
|
|
7180
|
+
source("packages/core/src/render-result-collector.ts"),
|
|
7181
7181
|
source("apps/skillset/src/import.ts"),
|
|
7182
7182
|
source("apps/skillset/src/setup.ts"),
|
|
7183
|
-
test("packages/core/src/__tests__/
|
|
7184
|
-
test("packages/core/src/__tests__/
|
|
7185
|
-
test("apps/skillset/src/__tests__/contract.test.ts", "SET-86 import and build warnings carry
|
|
7186
|
-
test("apps/skillset/src/__tests__/adopt.test.ts", "SET-86 adopt survey skips carry
|
|
7183
|
+
test("packages/core/src/__tests__/render-result.test.ts", "render result schema validation coverage"),
|
|
7184
|
+
test("packages/core/src/__tests__/render-result-build.test.ts", "build render results cover rendered, target-native, transformed, unsupported, policy-gated, scoped, and status-matrix results"),
|
|
7185
|
+
test("apps/skillset/src/__tests__/contract.test.ts", "SET-86 import and build warnings carry render result codes"),
|
|
7186
|
+
test("apps/skillset/src/__tests__/adopt.test.ts", "SET-86 adopt survey skips carry render result codes")
|
|
7187
7187
|
],
|
|
7188
|
-
id: "
|
|
7188
|
+
id: "render-results",
|
|
7189
7189
|
kind: "workflow",
|
|
7190
|
-
|
|
7191
|
-
sourceShape: "rendered build graph, generated lock items, companion files, unsupported feature records, and
|
|
7190
|
+
renderOwner: "packages/core/src/render-result-collector.ts",
|
|
7191
|
+
sourceShape: "rendered build graph, generated lock items, companion files, unsupported feature records, and render-relevant import/adopt report warnings",
|
|
7192
7192
|
status: "implemented",
|
|
7193
|
-
summary: "Records per-build
|
|
7193
|
+
summary: "Records per-build render facts for rendered, transformed, degraded, skipped, unsupported, and externally managed source units.",
|
|
7194
7194
|
targetSupport: notTargetRuntime(),
|
|
7195
|
-
title: "
|
|
7196
|
-
validationOwner: "packages/core/src/
|
|
7195
|
+
title: "Render Results",
|
|
7196
|
+
validationOwner: "packages/core/src/render-result.ts"
|
|
7197
7197
|
}),
|
|
7198
7198
|
feature({
|
|
7199
7199
|
docs: ["docs/features/output-safety.md"],
|
|
@@ -7204,7 +7204,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7204
7204
|
],
|
|
7205
7205
|
id: "output-safety",
|
|
7206
7206
|
kind: "workflow",
|
|
7207
|
-
|
|
7207
|
+
renderOwner: "packages/core/src/output-safety.ts",
|
|
7208
7208
|
sourceShape: "generated .skillset.lock ownership plus current rendered output paths",
|
|
7209
7209
|
status: "implemented",
|
|
7210
7210
|
summary: "Protects unmanaged generated-output collisions and target-side edits with reversible backups.",
|
|
@@ -7217,7 +7217,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7217
7217
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-26 MCP pointer coverage")],
|
|
7218
7218
|
id: "plugin-mcp",
|
|
7219
7219
|
kind: "plugin-component",
|
|
7220
|
-
|
|
7220
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7221
7221
|
sourceShape: "plugin mcp/source pointer or conventional .mcp.json",
|
|
7222
7222
|
status: "implemented",
|
|
7223
7223
|
summary: "Copies validated plugin MCP server definitions into Claude and Codex plugin outputs.",
|
|
@@ -7234,7 +7234,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7234
7234
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "Codex app manifest companion-path coverage")],
|
|
7235
7235
|
id: "plugin-apps",
|
|
7236
7236
|
kind: "target-native",
|
|
7237
|
-
|
|
7237
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7238
7238
|
sourceShape: "plugin codex/.app.json target-native companion file",
|
|
7239
7239
|
status: "implemented",
|
|
7240
7240
|
summary: "Passes Codex app manifests through as target-native plugin companion files.",
|
|
@@ -7260,7 +7260,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7260
7260
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-26 bin pointer coverage")],
|
|
7261
7261
|
id: "plugin-bin",
|
|
7262
7262
|
kind: "plugin-component",
|
|
7263
|
-
|
|
7263
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7264
7264
|
sourceShape: "plugin bin/source pointer or conventional bin/",
|
|
7265
7265
|
status: "implemented",
|
|
7266
7266
|
summary: "Copies Claude plugin-root executable helpers while failing loudly for Codex-enabled plugin output.",
|
|
@@ -7297,7 +7297,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7297
7297
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-2 hook companion-path coverage")],
|
|
7298
7298
|
id: "plugin-hooks",
|
|
7299
7299
|
kind: "target-native",
|
|
7300
|
-
|
|
7300
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7301
7301
|
sourceShape: "plugin hooks/hooks.json",
|
|
7302
7302
|
status: "implemented",
|
|
7303
7303
|
summary: "Copies plugin hook declarations with broad Claude validation and strict Codex validation.",
|
|
@@ -7328,8 +7328,8 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7328
7328
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "plugin boundary and manifest coverage")],
|
|
7329
7329
|
id: "plugin-manifests",
|
|
7330
7330
|
kind: "source",
|
|
7331
|
-
|
|
7332
|
-
sourceShape: ".skillset/plugins/<plugin>/skillset.yaml",
|
|
7331
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7332
|
+
sourceShape: ".skillset/src/plugins/<plugin>/skillset.yaml",
|
|
7333
7333
|
status: "implemented",
|
|
7334
7334
|
summary: "Projects plugin metadata and component wiring into target-native plugin manifests.",
|
|
7335
7335
|
targetSupport: bothTargets("native", [
|
|
@@ -7387,8 +7387,8 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7387
7387
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "plugin skill rendering coverage")],
|
|
7388
7388
|
id: "plugin-skills",
|
|
7389
7389
|
kind: "source",
|
|
7390
|
-
|
|
7391
|
-
sourceShape: ".skillset/plugins/<plugin>/skills/<skill>/SKILL.md",
|
|
7390
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7391
|
+
sourceShape: ".skillset/src/plugins/<plugin>/skills/<skill>/SKILL.md",
|
|
7392
7392
|
status: "implemented",
|
|
7393
7393
|
summary: "Preserves plugin-scoped skills inside each target plugin boundary.",
|
|
7394
7394
|
targetSupport: bothTargets("native"),
|
|
@@ -7421,7 +7421,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7421
7421
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "Codex plugin-agent failure coverage")],
|
|
7422
7422
|
id: "plugin-agents",
|
|
7423
7423
|
kind: "target-native",
|
|
7424
|
-
|
|
7424
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7425
7425
|
sourceShape: "plugin target-native agents/",
|
|
7426
7426
|
status: "implemented",
|
|
7427
7427
|
summary: "Allows Claude plugin agents as target-native companion files and rejects Codex plugin agents.",
|
|
@@ -7441,13 +7441,13 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7441
7441
|
}),
|
|
7442
7442
|
feature({
|
|
7443
7443
|
docs: ["docs/features/instructions.md"],
|
|
7444
|
-
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-5 instruction
|
|
7444
|
+
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-5 instruction rendering coverage")],
|
|
7445
7445
|
id: "project-instructions",
|
|
7446
7446
|
kind: "source",
|
|
7447
|
-
|
|
7448
|
-
sourceShape: ".skillset/
|
|
7447
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7448
|
+
sourceShape: ".skillset/src/rules/**/*.md",
|
|
7449
7449
|
status: "implemented",
|
|
7450
|
-
summary: "
|
|
7450
|
+
summary: "Renders project instructions to Claude rules and directory-local Codex AGENTS.md files.",
|
|
7451
7451
|
targetSupport: bothTargets("transformed"),
|
|
7452
7452
|
title: "Project Instructions",
|
|
7453
7453
|
validationOwner: "packages/core/src/resolver.ts"
|
|
@@ -7457,10 +7457,10 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7457
7457
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "portable project agent coverage")],
|
|
7458
7458
|
id: "project-agents",
|
|
7459
7459
|
kind: "source",
|
|
7460
|
-
|
|
7460
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7461
7461
|
sourceShape: ".skillset/src/agents/*.md",
|
|
7462
7462
|
status: "implemented",
|
|
7463
|
-
summary: "
|
|
7463
|
+
summary: "Renders portable project agents to Claude Markdown agents and Codex TOML agents.",
|
|
7464
7464
|
runtimeSupport: {
|
|
7465
7465
|
"claude-code": {
|
|
7466
7466
|
evidence: [docs("docs/features/agents.md"), externalDocs("https://code.claude.com/docs/en/sub-agents", "2026-06-04")],
|
|
@@ -7494,7 +7494,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7494
7494
|
evidence: [docs("docs/features/runtime-adapters.md"), test("packages/core/src/__tests__/feature-registry.test.ts", "SET-113 runtime support coverage")],
|
|
7495
7495
|
id: "runtime-adapters",
|
|
7496
7496
|
kind: "workflow",
|
|
7497
|
-
|
|
7497
|
+
renderOwner: "packages/core/src/feature-registry.ts",
|
|
7498
7498
|
runtimeSupport: {
|
|
7499
7499
|
"claude-code": {
|
|
7500
7500
|
evidence: [docs("docs/features/runtime-adapters.md")],
|
|
@@ -7549,7 +7549,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7549
7549
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-38 release apply coverage")],
|
|
7550
7550
|
id: "releases",
|
|
7551
7551
|
kind: "change-management",
|
|
7552
|
-
|
|
7552
|
+
renderOwner: "apps/skillset/src/release.ts",
|
|
7553
7553
|
sourceShape: ".skillset/releases/*.jsonl, .skillset/release-state.json, generated changelogs",
|
|
7554
7554
|
status: "implemented",
|
|
7555
7555
|
summary: "Applies pending changes into versions, release history, changelogs, and generated metadata.",
|
|
@@ -7562,8 +7562,8 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7562
7562
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "shared resource rendering coverage")],
|
|
7563
7563
|
id: "resources",
|
|
7564
7564
|
kind: "source",
|
|
7565
|
-
|
|
7566
|
-
sourceShape: "skill resources frontmatter and .skillset/shared/",
|
|
7565
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7566
|
+
sourceShape: "skill resources frontmatter and .skillset/src/shared/",
|
|
7567
7567
|
status: "implemented",
|
|
7568
7568
|
summary: "Copies declared skill resources and validates links to shared resource declarations.",
|
|
7569
7569
|
targetSupport: bothTargets("native"),
|
|
@@ -7575,8 +7575,8 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7575
7575
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "standalone skill rendering coverage")],
|
|
7576
7576
|
id: "standalone-skills",
|
|
7577
7577
|
kind: "source",
|
|
7578
|
-
|
|
7579
|
-
sourceShape: ".skillset/skills/<skill>/SKILL.md",
|
|
7578
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7579
|
+
sourceShape: ".skillset/src/skills/<skill>/SKILL.md",
|
|
7580
7580
|
status: "implemented",
|
|
7581
7581
|
summary: "Projects standalone repo skills into configured target skill roots.",
|
|
7582
7582
|
targetSupport: bothTargets("native"),
|
|
@@ -7588,7 +7588,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7588
7588
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-39 supports coverage")],
|
|
7589
7589
|
id: "supports",
|
|
7590
7590
|
kind: "metadata",
|
|
7591
|
-
|
|
7591
|
+
renderOwner: "apps/skillset/src/change-status.ts",
|
|
7592
7592
|
sourceShape: "supports frontmatter metadata",
|
|
7593
7593
|
status: "implemented",
|
|
7594
7594
|
summary: "Records compatibility claims as source-significant metadata without target-frontmatter leakage.",
|
|
@@ -7601,8 +7601,8 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7601
7601
|
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "target-native island coverage")],
|
|
7602
7602
|
id: "target-native-islands",
|
|
7603
7603
|
kind: "target-native",
|
|
7604
|
-
|
|
7605
|
-
sourceShape: ".skillset/src
|
|
7604
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7605
|
+
sourceShape: ".skillset/src/_claude/**, .skillset/src/_codex/**, and plugin-local provider source subdirs",
|
|
7606
7606
|
status: "implemented",
|
|
7607
7607
|
summary: "Mirrors explicitly target-owned files only to their intended provider output.",
|
|
7608
7608
|
targetSupport: bothTargets("pass_through"),
|
|
@@ -7611,10 +7611,10 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7611
7611
|
}),
|
|
7612
7612
|
feature({
|
|
7613
7613
|
docs: ["docs/features/tool-intent.md"],
|
|
7614
|
-
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "tool policy
|
|
7614
|
+
evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "tool policy rendering coverage")],
|
|
7615
7615
|
id: "tool-intent",
|
|
7616
7616
|
kind: "source",
|
|
7617
|
-
|
|
7617
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7618
7618
|
sourceShape: "skill tool_intent frontmatter",
|
|
7619
7619
|
status: "implemented",
|
|
7620
7620
|
summary: "Normalizes tool policy intent into Claude allowed-tools fields and Codex metadata sidecars.",
|
|
@@ -7630,7 +7630,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7630
7630
|
evidence: [docs("docs/target-surfaces.md")],
|
|
7631
7631
|
id: "future-companion-source-pointers",
|
|
7632
7632
|
kind: "plugin-component",
|
|
7633
|
-
|
|
7633
|
+
renderOwner: "future",
|
|
7634
7634
|
sourceShape: "future apps.source/hooks.source/commands.source/settings.source style feature keys",
|
|
7635
7635
|
status: "planned",
|
|
7636
7636
|
summary: "Reserved space for future companion-file source pointers beyond current MCP and bin feature keys.",
|
|
@@ -7646,7 +7646,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7646
7646
|
evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-111 release audit coverage")],
|
|
7647
7647
|
id: "version-audit",
|
|
7648
7648
|
kind: "change-management",
|
|
7649
|
-
|
|
7649
|
+
renderOwner: "packages/core/src/version-audit.ts",
|
|
7650
7650
|
sourceShape: "release state and generated version loci",
|
|
7651
7651
|
status: "implemented",
|
|
7652
7652
|
summary: "Audits generated version fields against source and release-state authorities without writing.",
|
|
@@ -7659,10 +7659,10 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7659
7659
|
evidence: [test("apps/skillset/src/__tests__/ci.test.ts", "CI and build-scope coverage")],
|
|
7660
7660
|
id: "workflows",
|
|
7661
7661
|
kind: "workflow",
|
|
7662
|
-
|
|
7662
|
+
renderOwner: "apps/skillset/src/cli-core.ts",
|
|
7663
7663
|
sourceShape: "skillset CLI workflows such as build, check, ci, test, init, and create",
|
|
7664
7664
|
status: "implemented",
|
|
7665
|
-
summary: "Provides repo-local workflow commands without
|
|
7665
|
+
summary: "Provides repo-local workflow commands without rendering them into target runtime artifacts.",
|
|
7666
7666
|
targetSupport: notTargetRuntime(),
|
|
7667
7667
|
title: "Workflows",
|
|
7668
7668
|
validationOwner: "apps/skillset/src/cli-core.ts"
|
|
@@ -7757,7 +7757,7 @@ function pluginCompanionFeature(entry) {
|
|
|
7757
7757
|
evidence: [source("packages/core/src/render.ts")],
|
|
7758
7758
|
id: entry.id,
|
|
7759
7759
|
kind: "target-native",
|
|
7760
|
-
|
|
7760
|
+
renderOwner: "packages/core/src/render.ts",
|
|
7761
7761
|
sourceShape: entry.sourceShape,
|
|
7762
7762
|
status: "implemented",
|
|
7763
7763
|
summary: entry.summary,
|
|
@@ -7796,44 +7796,45 @@ function fixture(ref) {
|
|
|
7796
7796
|
return { kind: "fixture", ref };
|
|
7797
7797
|
}
|
|
7798
7798
|
|
|
7799
|
-
// packages/core/src/
|
|
7800
|
-
var
|
|
7801
|
-
var
|
|
7799
|
+
// packages/core/src/render-result.ts
|
|
7800
|
+
var RENDER_RESULT_SCHEMA = "skillset-render-result@1";
|
|
7801
|
+
var RENDER_RESULT_STATUS_VALUES = [
|
|
7802
7802
|
"degraded",
|
|
7803
|
-
"emitted",
|
|
7804
7803
|
"externally_managed",
|
|
7805
7804
|
"failed",
|
|
7806
7805
|
"intentionally_skipped",
|
|
7807
7806
|
"lossy",
|
|
7808
7807
|
"metadata_only",
|
|
7808
|
+
"rendered",
|
|
7809
7809
|
"target_native",
|
|
7810
7810
|
"transformed",
|
|
7811
7811
|
"unsupported"
|
|
7812
7812
|
];
|
|
7813
7813
|
|
|
7814
|
-
class
|
|
7815
|
-
|
|
7816
|
-
constructor(message,
|
|
7814
|
+
class SkillsetRenderResultError extends Error {
|
|
7815
|
+
renderResults;
|
|
7816
|
+
constructor(message, renderResults) {
|
|
7817
7817
|
super(message);
|
|
7818
|
-
this.name = "
|
|
7819
|
-
this.
|
|
7818
|
+
this.name = "SkillsetRenderResultError";
|
|
7819
|
+
this.renderResults = renderResults.map(normalizeRenderResult);
|
|
7820
7820
|
}
|
|
7821
7821
|
}
|
|
7822
|
-
function
|
|
7823
|
-
const outcome =
|
|
7822
|
+
function defineRenderResult(input) {
|
|
7823
|
+
const outcome = normalizeRenderResult({
|
|
7824
7824
|
...input,
|
|
7825
|
-
schema: input.schema ??
|
|
7825
|
+
schema: input.schema ?? RENDER_RESULT_SCHEMA
|
|
7826
7826
|
});
|
|
7827
|
-
|
|
7827
|
+
assertRenderResult(outcome);
|
|
7828
7828
|
return outcome;
|
|
7829
7829
|
}
|
|
7830
|
-
function
|
|
7830
|
+
function normalizeRenderResult(outcome) {
|
|
7831
7831
|
return {
|
|
7832
7832
|
schema: outcome.schema,
|
|
7833
7833
|
sourceUnit: outcome.sourceUnit,
|
|
7834
7834
|
...outcome.sourcePath === undefined ? {} : { sourcePath: outcome.sourcePath },
|
|
7835
7835
|
featureId: outcome.featureId,
|
|
7836
7836
|
...outcome.target === undefined ? {} : { target: outcome.target },
|
|
7837
|
+
...outcome.destination === undefined ? {} : { destination: outcome.destination },
|
|
7837
7838
|
status: outcome.status,
|
|
7838
7839
|
...outcome.reason === undefined ? {} : { reason: outcome.reason },
|
|
7839
7840
|
...outcome.policy === undefined ? {} : { policy: outcome.policy },
|
|
@@ -7842,38 +7843,41 @@ function normalizeLoweringOutcome(outcome) {
|
|
|
7842
7843
|
...outcome.evidence === undefined ? {} : { evidence: normalizeEvidence(outcome.evidence) }
|
|
7843
7844
|
};
|
|
7844
7845
|
}
|
|
7845
|
-
function
|
|
7846
|
-
if (outcome.schema !==
|
|
7847
|
-
throw new Error(`skillset: unsupported
|
|
7846
|
+
function assertRenderResult(outcome) {
|
|
7847
|
+
if (outcome.schema !== RENDER_RESULT_SCHEMA) {
|
|
7848
|
+
throw new Error(`skillset: unsupported render result schema ${outcome.schema}`);
|
|
7848
7849
|
}
|
|
7849
7850
|
if (outcome.sourceUnit.trim().length === 0) {
|
|
7850
|
-
throw new Error("skillset:
|
|
7851
|
+
throw new Error("skillset: render result sourceUnit is required");
|
|
7851
7852
|
}
|
|
7852
7853
|
if (outcome.featureId.trim().length === 0) {
|
|
7853
|
-
throw new Error("skillset:
|
|
7854
|
+
throw new Error("skillset: render result featureId is required");
|
|
7854
7855
|
}
|
|
7855
|
-
if (
|
|
7856
|
-
throw new Error(
|
|
7856
|
+
if (outcome.destination !== undefined && outcome.destination.trim().length === 0) {
|
|
7857
|
+
throw new Error("skillset: render result destination must be non-empty when present");
|
|
7858
|
+
}
|
|
7859
|
+
if (!new Set(RENDER_RESULT_STATUS_VALUES).has(outcome.status)) {
|
|
7860
|
+
throw new Error(`skillset: unknown render result status ${outcome.status}`);
|
|
7857
7861
|
}
|
|
7858
7862
|
if ((outcome.status === "degraded" || outcome.status === "failed" || outcome.status === "lossy" || outcome.status === "unsupported") && outcome.reason === undefined) {
|
|
7859
|
-
throw new Error(`skillset:
|
|
7863
|
+
throw new Error(`skillset: render result ${outcome.status} status requires a reason`);
|
|
7860
7864
|
}
|
|
7861
7865
|
for (const output of outcome.outputs ?? []) {
|
|
7862
7866
|
if (output.path.trim().length === 0) {
|
|
7863
|
-
throw new Error("skillset:
|
|
7867
|
+
throw new Error("skillset: render result output path is required");
|
|
7864
7868
|
}
|
|
7865
7869
|
}
|
|
7866
7870
|
for (const diagnostic of outcome.diagnostics ?? []) {
|
|
7867
7871
|
if (diagnostic.code.trim().length === 0) {
|
|
7868
|
-
throw new Error("skillset:
|
|
7872
|
+
throw new Error("skillset: render result diagnostic code is required");
|
|
7869
7873
|
}
|
|
7870
7874
|
}
|
|
7871
7875
|
for (const evidence of outcome.evidence ?? []) {
|
|
7872
7876
|
if (evidence.ref.trim().length === 0) {
|
|
7873
|
-
throw new Error("skillset:
|
|
7877
|
+
throw new Error("skillset: render result evidence ref is required");
|
|
7874
7878
|
}
|
|
7875
7879
|
if (evidence.kind === "external-docs" && evidence.verifiedAt === undefined) {
|
|
7876
|
-
throw new Error("skillset:
|
|
7880
|
+
throw new Error("skillset: render result external docs evidence requires verifiedAt");
|
|
7877
7881
|
}
|
|
7878
7882
|
}
|
|
7879
7883
|
}
|
|
@@ -7899,7 +7903,7 @@ function normalizeEvidence(evidence) {
|
|
|
7899
7903
|
})).sort((left, right) => compareStrings(`${left.kind}\x00${left.ref}\x00${left.verifiedAt ?? ""}\x00${left.note ?? ""}`, `${right.kind}\x00${right.ref}\x00${right.verifiedAt ?? ""}\x00${right.note ?? ""}`));
|
|
7900
7904
|
}
|
|
7901
7905
|
|
|
7902
|
-
// packages/core/src/
|
|
7906
|
+
// packages/core/src/render-result-collector.ts
|
|
7903
7907
|
import { existsSync, readdirSync, statSync } from "fs";
|
|
7904
7908
|
import { join, relative as relative2 } from "path";
|
|
7905
7909
|
|
|
@@ -7992,8 +7996,10 @@ var TARGET_NAMES = ["claude", "codex"];
|
|
|
7992
7996
|
var DEFAULT_SURFACES = new Set(["agents", "instructions", "plugins", "skills"]);
|
|
7993
7997
|
var CONFIG_TOP_LEVEL_KEYS = new Set(["agents", "changes", "claude", "codex", "defaults", "dependencies", "skillset", "supports"]);
|
|
7994
7998
|
var ROOT_CONFIG_TOP_LEVEL_KEYS = new Set([...CONFIG_TOP_LEVEL_KEYS, "compile", "distributions", "tests"]);
|
|
7999
|
+
var WORKSPACE_CONFIG_TOP_LEVEL_KEYS = new Set(["agents", "changes", "claude", "codex", "compile", "defaults", "dependencies", "distributions", "tests"]);
|
|
8000
|
+
var ROOT_SOURCE_MANIFEST_TOP_LEVEL_KEYS = new Set(["dependencies", "skillset", "supports"]);
|
|
7995
8001
|
var COMPILE_BUILD_MODES = new Set(["updated", "all"]);
|
|
7996
|
-
var
|
|
8002
|
+
var UNSUPPORTED_DESTINATION_POLICIES = new Set([
|
|
7997
8003
|
"error",
|
|
7998
8004
|
"warn",
|
|
7999
8005
|
"skip",
|
|
@@ -8042,23 +8048,23 @@ function readCompileConfig(record, label) {
|
|
|
8042
8048
|
build: "updated",
|
|
8043
8049
|
skillset: { metadata: true },
|
|
8044
8050
|
targets: [...TARGET_NAMES],
|
|
8045
|
-
|
|
8051
|
+
unsupportedDestination: "error"
|
|
8046
8052
|
};
|
|
8047
8053
|
}
|
|
8048
8054
|
for (const key of Object.keys(compile)) {
|
|
8049
|
-
if (key !== "build" && key !== "skillset" && key !== "targets" && key !== "
|
|
8055
|
+
if (key !== "build" && key !== "skillset" && key !== "targets" && key !== "unsupportedDestination") {
|
|
8050
8056
|
throw new Error(`skillset: unsupported compile key ${key} in ${label}`);
|
|
8051
8057
|
}
|
|
8052
8058
|
}
|
|
8053
|
-
const
|
|
8054
|
-
if (
|
|
8055
|
-
throw new Error(`skillset: ${label}.compile.
|
|
8059
|
+
const unsupportedDestination = readUnsupportedDestinationPolicy(compile, `${label}.compile.unsupportedDestination`);
|
|
8060
|
+
if (unsupportedDestination !== "error") {
|
|
8061
|
+
throw new Error(`skillset: ${label}.compile.unsupportedDestination ${unsupportedDestination} is reserved but not supported yet; ` + "use error until warning, skip, or force provenance is implemented");
|
|
8056
8062
|
}
|
|
8057
8063
|
return {
|
|
8058
8064
|
build: readCompileBuildMode(compile, `${label}.compile.build`),
|
|
8059
8065
|
skillset: readCompileSkillsetConfig(compile, `${label}.compile.skillset`),
|
|
8060
8066
|
targets: readCompileTargetNames(compile, `${label}.compile.targets`),
|
|
8061
|
-
|
|
8067
|
+
unsupportedDestination
|
|
8062
8068
|
};
|
|
8063
8069
|
}
|
|
8064
8070
|
function readCompileTargets(record, label) {
|
|
@@ -8180,6 +8186,22 @@ function validateConfigDocument(record, label, options = {}) {
|
|
|
8180
8186
|
}
|
|
8181
8187
|
}
|
|
8182
8188
|
}
|
|
8189
|
+
function validateWorkspaceConfigDocument(record, label) {
|
|
8190
|
+
rejectTargetsKey(record, label);
|
|
8191
|
+
for (const key of Object.keys(record)) {
|
|
8192
|
+
if (!WORKSPACE_CONFIG_TOP_LEVEL_KEYS.has(key)) {
|
|
8193
|
+
throw new Error(`skillset: unsupported workspace config key ${key} in ${label}; ` + "move source identity and compatibility metadata to .skillset/src/skillset.yaml");
|
|
8194
|
+
}
|
|
8195
|
+
}
|
|
8196
|
+
}
|
|
8197
|
+
function validateRootSourceManifestDocument(record, label) {
|
|
8198
|
+
rejectTargetsKey(record, label);
|
|
8199
|
+
for (const key of Object.keys(record)) {
|
|
8200
|
+
if (!ROOT_SOURCE_MANIFEST_TOP_LEVEL_KEYS.has(key)) {
|
|
8201
|
+
throw new Error(`skillset: unsupported root source manifest key ${key} in ${label}`);
|
|
8202
|
+
}
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8183
8205
|
function resolveTargets(parent, record, label, options = {}) {
|
|
8184
8206
|
rejectTargetsKey(record, label);
|
|
8185
8207
|
if (record.defaults !== undefined && options.allowDefaults !== true) {
|
|
@@ -8333,14 +8355,14 @@ function readCompileSkillsetConfig(record, label) {
|
|
|
8333
8355
|
}
|
|
8334
8356
|
return { metadata };
|
|
8335
8357
|
}
|
|
8336
|
-
function
|
|
8337
|
-
const value = record.
|
|
8358
|
+
function readUnsupportedDestinationPolicy(record, label) {
|
|
8359
|
+
const value = record.unsupportedDestination;
|
|
8338
8360
|
if (value === undefined)
|
|
8339
8361
|
return "error";
|
|
8340
8362
|
if (typeof value !== "string") {
|
|
8341
8363
|
throw new Error(`skillset: expected ${label} to be one of: error, warn, skip, force`);
|
|
8342
8364
|
}
|
|
8343
|
-
if (!
|
|
8365
|
+
if (!UNSUPPORTED_DESTINATION_POLICIES.has(value)) {
|
|
8344
8366
|
throw new Error(`skillset: unsupported ${label} ${JSON.stringify(value)}; expected one of: error, warn, skip, force`);
|
|
8345
8367
|
}
|
|
8346
8368
|
return value;
|
|
@@ -9087,10 +9109,10 @@ function targetNativeSurface(relativePath) {
|
|
|
9087
9109
|
return first.replace(/[^A-Za-z0-9-]/g, "") || "native";
|
|
9088
9110
|
}
|
|
9089
9111
|
|
|
9090
|
-
// packages/core/src/
|
|
9112
|
+
// packages/core/src/render-result-collector.ts
|
|
9091
9113
|
var LOCK_FILE = ".skillset.lock";
|
|
9092
9114
|
var TARGETS2 = ["claude", "codex"];
|
|
9093
|
-
function
|
|
9115
|
+
function collectRenderResults(graph, rendered, options) {
|
|
9094
9116
|
const mapOutputPath = options.mapOutputPath ?? ((path) => path);
|
|
9095
9117
|
const outcomes = [];
|
|
9096
9118
|
const assignedOutputPaths = new Set;
|
|
@@ -9113,18 +9135,18 @@ function collectLoweringOutcomes(graph, rendered, options) {
|
|
|
9113
9135
|
outcomes.push(outcome);
|
|
9114
9136
|
}
|
|
9115
9137
|
outcomes.push(...unsupportedPluginFeatureOutcomes(graph, options.scopes));
|
|
9116
|
-
return outcomes.sort((left, right) => compareStrings(`${left.sourceUnit}\x00${left.target ?? ""}\x00${left.featureId}\x00${left.status}\x00${left.sourcePath ?? ""}`, `${right.sourceUnit}\x00${right.target ?? ""}\x00${right.featureId}\x00${right.status}\x00${right.sourcePath ?? ""}`));
|
|
9138
|
+
return outcomes.sort((left, right) => compareStrings(`${left.sourceUnit}\x00${left.target ?? ""}\x00${left.featureId}\x00${left.destination ?? ""}\x00${left.status}\x00${left.sourcePath ?? ""}`, `${right.sourceUnit}\x00${right.target ?? ""}\x00${right.featureId}\x00${right.destination ?? ""}\x00${right.status}\x00${right.sourcePath ?? ""}`));
|
|
9117
9139
|
}
|
|
9118
9140
|
function parseRenderedLock(file) {
|
|
9119
9141
|
const parsed = JSON.parse(new TextDecoder().decode(file.content));
|
|
9120
9142
|
if (!isJsonRecord(parsed)) {
|
|
9121
|
-
throw new Error(`skillset: generated lock ${file.path} cannot produce
|
|
9143
|
+
throw new Error(`skillset: generated lock ${file.path} cannot produce render results`);
|
|
9122
9144
|
}
|
|
9123
9145
|
const outputRoot = stringField(parsed, "outputRoot");
|
|
9124
9146
|
const target = stringField(parsed, "target");
|
|
9125
9147
|
const rawItems = parsed.items;
|
|
9126
9148
|
if (!Array.isArray(rawItems)) {
|
|
9127
|
-
throw new Error(`skillset: generated lock ${file.path} cannot produce
|
|
9149
|
+
throw new Error(`skillset: generated lock ${file.path} cannot produce render results`);
|
|
9128
9150
|
}
|
|
9129
9151
|
return {
|
|
9130
9152
|
items: rawItems.map((item) => parseRenderedLockItem(file.path, item)),
|
|
@@ -9165,7 +9187,8 @@ function outcomeForLockItem(graph, lock, item, outputPaths, includedPaths, mapOu
|
|
|
9165
9187
|
const policy = isIncluded ? undefined : "scope:excluded";
|
|
9166
9188
|
const reason = isIncluded ? reasonForStatus(featureId, target, status) : "excluded by build scope";
|
|
9167
9189
|
const evidence = evidenceFor(featureId, target);
|
|
9168
|
-
return
|
|
9190
|
+
return defineRenderResult({
|
|
9191
|
+
destination: destinationForLockItem(item),
|
|
9169
9192
|
...evidence === undefined ? {} : { evidence },
|
|
9170
9193
|
featureId,
|
|
9171
9194
|
...isIncluded ? { outputs: outputPaths.map((path) => ({ kind: item.kind, path: mapOutputPath(path) })) } : {},
|
|
@@ -9184,7 +9207,8 @@ function outcomeForCompanionFile(graph, file, isIncluded, mapOutputPath) {
|
|
|
9184
9207
|
const plugin = graph.plugins.find((candidate) => candidate.id === companion.pluginId);
|
|
9185
9208
|
const sourcePath = plugin === undefined ? undefined : normalizePath(relative2(graph.rootPath, join(plugin.path, companion.sourceRelativePath)));
|
|
9186
9209
|
const evidence = evidenceFor(companion.featureId, companion.target);
|
|
9187
|
-
return
|
|
9210
|
+
return defineRenderResult({
|
|
9211
|
+
destination: companion.featureKey,
|
|
9188
9212
|
...evidence === undefined ? {} : { evidence },
|
|
9189
9213
|
featureId: companion.featureId,
|
|
9190
9214
|
...isIncluded ? { outputs: [{ kind: "companion", path: mapOutputPath(file.path) }] } : {},
|
|
@@ -9200,6 +9224,7 @@ function featureOutcomesForLockItem(graph, lock, item, outputPaths, includedPath
|
|
|
9200
9224
|
const outcomes = [];
|
|
9201
9225
|
if (item.kind === "plugin" && item.dependencies !== undefined && item.dependencies.length > 0) {
|
|
9202
9226
|
outcomes.push(featureOutcome({
|
|
9227
|
+
destination: "plugin-manifest",
|
|
9203
9228
|
featureId: "dependencies",
|
|
9204
9229
|
isIncluded: outputPaths.some((path) => includedPaths.has(path)),
|
|
9205
9230
|
mapOutputPath,
|
|
@@ -9207,13 +9232,14 @@ function featureOutcomesForLockItem(graph, lock, item, outputPaths, includedPath
|
|
|
9207
9232
|
outputPaths,
|
|
9208
9233
|
sourcePath: item.sourcePath,
|
|
9209
9234
|
sourceUnit: selectorForPluginFeature(item.name, "dependencies"),
|
|
9210
|
-
status: target === "codex" ? "degraded" : "
|
|
9235
|
+
status: target === "codex" ? "degraded" : "rendered",
|
|
9211
9236
|
target
|
|
9212
9237
|
}));
|
|
9213
9238
|
}
|
|
9214
9239
|
const claudeToolIntentOutputPaths = target === "claude" && skillHasClaudeToolIntent(graph, item) ? outputPaths.filter((path) => path.endsWith("/SKILL.md") || path === "SKILL.md") : [];
|
|
9215
9240
|
if (claudeToolIntentOutputPaths.length > 0) {
|
|
9216
9241
|
outcomes.push(featureOutcome({
|
|
9242
|
+
destination: "skill-frontmatter",
|
|
9217
9243
|
featureId: "tool-intent",
|
|
9218
9244
|
isIncluded: claudeToolIntentOutputPaths.some((path) => includedPaths.has(path)),
|
|
9219
9245
|
mapOutputPath,
|
|
@@ -9228,6 +9254,7 @@ function featureOutcomesForLockItem(graph, lock, item, outputPaths, includedPath
|
|
|
9228
9254
|
const toolIntentOutputPaths = outputPaths.filter((path) => path.endsWith("/.skillset.tools.yaml"));
|
|
9229
9255
|
if (toolIntentOutputPaths.length > 0) {
|
|
9230
9256
|
outcomes.push(featureOutcome({
|
|
9257
|
+
destination: "skill-tools",
|
|
9231
9258
|
featureId: "tool-intent",
|
|
9232
9259
|
isIncluded: toolIntentOutputPaths.some((path) => includedPaths.has(path)),
|
|
9233
9260
|
mapOutputPath,
|
|
@@ -9260,7 +9287,8 @@ function featureOutcome(args) {
|
|
|
9260
9287
|
const status = args.isIncluded ? args.status : "intentionally_skipped";
|
|
9261
9288
|
const evidence = evidenceFor(args.featureId, args.target);
|
|
9262
9289
|
const reason = args.isIncluded ? reasonForStatus(args.featureId, args.target, status) : "excluded by build scope";
|
|
9263
|
-
return
|
|
9290
|
+
return defineRenderResult({
|
|
9291
|
+
destination: args.destination,
|
|
9264
9292
|
...evidence === undefined ? {} : { evidence },
|
|
9265
9293
|
featureId: args.featureId,
|
|
9266
9294
|
...args.isIncluded ? { outputs: args.outputPaths.map((path) => ({ kind: args.outputKind, path: args.mapOutputPath(path) })) } : {},
|
|
@@ -9285,7 +9313,8 @@ function unsupportedPluginFeatureOutcomes(graph, scopes) {
|
|
|
9285
9313
|
continue;
|
|
9286
9314
|
const featureId2 = "plugin-bin";
|
|
9287
9315
|
const evidence2 = evidenceFor(featureId2, "codex");
|
|
9288
|
-
outcomes.push(
|
|
9316
|
+
outcomes.push(defineRenderResult({
|
|
9317
|
+
destination: "bin",
|
|
9289
9318
|
...evidence2 === undefined ? {} : { evidence: evidence2 },
|
|
9290
9319
|
featureId: featureId2,
|
|
9291
9320
|
policy: "unsupported:error",
|
|
@@ -9301,7 +9330,8 @@ function unsupportedPluginFeatureOutcomes(graph, scopes) {
|
|
|
9301
9330
|
continue;
|
|
9302
9331
|
const featureId = "plugin-agents";
|
|
9303
9332
|
const evidence = evidenceFor(featureId, "codex");
|
|
9304
|
-
outcomes.push(
|
|
9333
|
+
outcomes.push(defineRenderResult({
|
|
9334
|
+
destination: "agents",
|
|
9305
9335
|
...evidence === undefined ? {} : { evidence },
|
|
9306
9336
|
featureId,
|
|
9307
9337
|
policy: "unsupported:error",
|
|
@@ -9362,6 +9392,23 @@ function featureIdForLockItem(item) {
|
|
|
9362
9392
|
return "plugin-bin";
|
|
9363
9393
|
return item.feature ?? item.kind;
|
|
9364
9394
|
}
|
|
9395
|
+
function destinationForLockItem(item) {
|
|
9396
|
+
if (item.kind === "standalone-skill" || item.kind === "plugin-skill")
|
|
9397
|
+
return "skill";
|
|
9398
|
+
if (item.kind === "plugin")
|
|
9399
|
+
return "plugin-manifest";
|
|
9400
|
+
if (item.kind === "rule")
|
|
9401
|
+
return "instruction";
|
|
9402
|
+
if (item.kind === "project-agent")
|
|
9403
|
+
return "agent";
|
|
9404
|
+
if (item.kind === "island")
|
|
9405
|
+
return "target-native-island";
|
|
9406
|
+
if (item.kind === "changelog")
|
|
9407
|
+
return "changelog";
|
|
9408
|
+
if (item.kind === "plugin-feature" && item.feature !== undefined)
|
|
9409
|
+
return item.feature;
|
|
9410
|
+
return item.feature ?? item.kind;
|
|
9411
|
+
}
|
|
9365
9412
|
function sourceUnitForLockItem(item, target) {
|
|
9366
9413
|
if (item.kind === "standalone-skill")
|
|
9367
9414
|
return selectorForStandaloneSkill(item.name);
|
|
@@ -9405,7 +9452,7 @@ function statusForLockItem(item, target) {
|
|
|
9405
9452
|
return "transformed";
|
|
9406
9453
|
if (item.validation === "opaque-copy")
|
|
9407
9454
|
return "target_native";
|
|
9408
|
-
return "
|
|
9455
|
+
return "rendered";
|
|
9409
9456
|
}
|
|
9410
9457
|
function targetForLockItem(graph, lock, item, outputPaths) {
|
|
9411
9458
|
if (lock.target !== "workspace")
|
|
@@ -9587,20 +9634,20 @@ function sourceWarningDiagnostic(message) {
|
|
|
9587
9634
|
import { mkdir as mkdir3, readdir as readdir4, readFile as readFile8, rm, stat as stat7, writeFile as writeFile3 } from "fs/promises";
|
|
9588
9635
|
import { dirname as dirname7, join as join9, relative as relative9 } from "path";
|
|
9589
9636
|
|
|
9590
|
-
// packages/core/src/
|
|
9591
|
-
function
|
|
9592
|
-
const blocked =
|
|
9637
|
+
// packages/core/src/render-result-policy.ts
|
|
9638
|
+
function enforceRenderResultPolicy(renderResults, unsupportedPolicy) {
|
|
9639
|
+
const blocked = renderResults.filter(isPolicyBlockingOutcome);
|
|
9593
9640
|
if (blocked.length === 0)
|
|
9594
9641
|
return;
|
|
9595
|
-
throw new
|
|
9642
|
+
throw new SkillsetRenderResultError(formatRenderResultPolicyError(blocked, unsupportedPolicy), blocked);
|
|
9596
9643
|
}
|
|
9597
9644
|
function isPolicyBlockingOutcome(outcome) {
|
|
9598
9645
|
return outcome.status === "failed" || outcome.status === "lossy" || outcome.status === "unsupported";
|
|
9599
9646
|
}
|
|
9600
|
-
function
|
|
9601
|
-
const noun = outcomes.length === 1 ? "
|
|
9647
|
+
function formatRenderResultPolicyError(outcomes, unsupportedPolicy) {
|
|
9648
|
+
const noun = outcomes.length === 1 ? "render result" : "render results";
|
|
9602
9649
|
return [
|
|
9603
|
-
`skillset:
|
|
9650
|
+
`skillset: unsupported destination policy blocked ${outcomes.length} ${noun} (compile.unsupportedDestination: ${unsupportedPolicy})`,
|
|
9604
9651
|
...outcomes.map(formatBlockedOutcome)
|
|
9605
9652
|
].join(`
|
|
9606
9653
|
`);
|
|
@@ -12028,7 +12075,7 @@ async function renderClaudeProjectAgent(graph, agent) {
|
|
|
12028
12075
|
preprocessDependencies,
|
|
12029
12076
|
rootPath: graph.rootPath,
|
|
12030
12077
|
sourcePath: agent.sourcePath,
|
|
12031
|
-
sourceRoot: graph.sourceDir
|
|
12078
|
+
sourceRoot: join6(graph.sourceDir, "src")
|
|
12032
12079
|
});
|
|
12033
12080
|
const targetPath = join6(targetProjectRoot2(graph, "claude"), "agents", `${agent.outputName}.md`);
|
|
12034
12081
|
return {
|
|
@@ -12064,7 +12111,7 @@ async function renderCodexProjectAgentInstructions(graph, agent, targetOptions,
|
|
|
12064
12111
|
preprocessDependencies,
|
|
12065
12112
|
rootPath: graph.rootPath,
|
|
12066
12113
|
sourcePath: agent.sourcePath,
|
|
12067
|
-
sourceRoot: graph.sourceDir
|
|
12114
|
+
sourceRoot: join6(graph.sourceDir, "src")
|
|
12068
12115
|
});
|
|
12069
12116
|
const sections = [];
|
|
12070
12117
|
if (skills !== undefined && skills.length > 0) {
|
|
@@ -12077,7 +12124,7 @@ async function renderCodexProjectAgentInstructions(graph, agent, targetOptions,
|
|
|
12077
12124
|
preprocessDependencies,
|
|
12078
12125
|
rootPath: graph.rootPath,
|
|
12079
12126
|
sourcePath: agent.sourcePath,
|
|
12080
|
-
sourceRoot: graph.sourceDir
|
|
12127
|
+
sourceRoot: join6(graph.sourceDir, "src")
|
|
12081
12128
|
});
|
|
12082
12129
|
if (renderedPrompt.includes("</initial_prompt>")) {
|
|
12083
12130
|
throw new Error(`skillset: ${relative7(graph.rootPath, agent.sourcePath)} initialPrompt must not contain </initial_prompt>`);
|
|
@@ -12168,7 +12215,7 @@ async function renderTextIslandFile(graph, island, targetPath, preprocessDepende
|
|
|
12168
12215
|
preprocessDependencies,
|
|
12169
12216
|
rootPath: graph.rootPath,
|
|
12170
12217
|
sourcePath: island.sourcePath,
|
|
12171
|
-
sourceRoot: graph.sourceDir
|
|
12218
|
+
sourceRoot: join6(graph.sourceDir, "src")
|
|
12172
12219
|
});
|
|
12173
12220
|
return renderValidatedMarkdown(stripSourceFrontmatter(parsed.frontmatter, island.sourcePath), body, `${relative7(graph.rootPath, island.sourcePath)} -> ${targetPath}`);
|
|
12174
12221
|
}
|
|
@@ -12177,7 +12224,7 @@ async function renderTextIslandFile(graph, island, targetPath, preprocessDepende
|
|
|
12177
12224
|
preprocessDependencies,
|
|
12178
12225
|
rootPath: graph.rootPath,
|
|
12179
12226
|
sourcePath: island.sourcePath,
|
|
12180
|
-
sourceRoot: graph.sourceDir
|
|
12227
|
+
sourceRoot: join6(graph.sourceDir, "src")
|
|
12181
12228
|
});
|
|
12182
12229
|
}
|
|
12183
12230
|
function rejectIslandTargetEscape(frontmatter, island) {
|
|
@@ -12289,7 +12336,7 @@ async function renderSkillMarkdown(graph, plugin, skill, target) {
|
|
|
12289
12336
|
frontmatter: skill.frontmatter,
|
|
12290
12337
|
rootPath: graph.rootPath,
|
|
12291
12338
|
sourcePath: skill.sourcePath,
|
|
12292
|
-
sourceRoot: graph.sourceDir,
|
|
12339
|
+
sourceRoot: join6(graph.sourceDir, "src"),
|
|
12293
12340
|
...plugin === undefined ? {} : { pluginPath: plugin.path }
|
|
12294
12341
|
});
|
|
12295
12342
|
const dependencyNotice = target === "codex" && plugin !== undefined ? renderCodexDependencyNotice(graph, plugin) : undefined;
|
|
@@ -12337,7 +12384,7 @@ async function renderCodexSkillAgentFile(graph, plugin, skill, target, sourceDir
|
|
|
12337
12384
|
frontmatter: skill.frontmatter,
|
|
12338
12385
|
rootPath: graph.rootPath,
|
|
12339
12386
|
sourcePath: sourceOpenAiPath,
|
|
12340
|
-
sourceRoot: graph.sourceDir,
|
|
12387
|
+
sourceRoot: join6(graph.sourceDir, "src"),
|
|
12341
12388
|
...plugin === undefined ? {} : { pluginPath: plugin.path }
|
|
12342
12389
|
}), sourceOpenAiPath) : {};
|
|
12343
12390
|
const merged = mergeRecords(source2, generated);
|
|
@@ -12521,7 +12568,7 @@ async function renderRuleBody(graph, rule, outputPath) {
|
|
|
12521
12568
|
frontmatter: rule.frontmatter,
|
|
12522
12569
|
rootPath: graph.rootPath,
|
|
12523
12570
|
sourcePath: rule.sourcePath,
|
|
12524
|
-
sourceRoot: graph.sourceDir,
|
|
12571
|
+
sourceRoot: join6(graph.sourceDir, "src"),
|
|
12525
12572
|
variables: ruleVariables(graph, rule, outputPath)
|
|
12526
12573
|
});
|
|
12527
12574
|
}
|
|
@@ -12700,7 +12747,7 @@ function renderLockFiles(graph, lockRoots) {
|
|
|
12700
12747
|
skillsetMetadata: graph.root.compile.skillset.metadata,
|
|
12701
12748
|
outputRoot,
|
|
12702
12749
|
schemaVersion: 1,
|
|
12703
|
-
sourceRoot: graph.sourceDir,
|
|
12750
|
+
sourceRoot: join6(graph.sourceDir, "src"),
|
|
12704
12751
|
target: lock.target
|
|
12705
12752
|
};
|
|
12706
12753
|
rendered.push(textFile(join6(outputRoot, ".skillset.lock"), renderValidatedJson(value, `${outputRoot}/.skillset.lock`)));
|
|
@@ -13205,26 +13252,35 @@ async function exists4(path) {
|
|
|
13205
13252
|
// packages/core/src/resolver.ts
|
|
13206
13253
|
var DEFAULT_SOURCE_DIR = ".skillset";
|
|
13207
13254
|
var ROOT_CONFIG_FILE = "config.yaml";
|
|
13255
|
+
var ROOT_SOURCE_MANIFEST_FILE = "skillset.yaml";
|
|
13208
13256
|
var PLUGIN_CONFIG_FILES = ["skillset.yaml", "config.yaml"];
|
|
13209
13257
|
var PLUGINS_DIR = "plugins";
|
|
13210
|
-
var
|
|
13258
|
+
var SOURCE_ROOT_DIR = "src";
|
|
13259
|
+
var RULES_DIR = "rules";
|
|
13211
13260
|
var SKILLS_DIR = "skills";
|
|
13261
|
+
var SHARED_DIR = "shared";
|
|
13212
13262
|
var SKILL_FILE = "SKILL.md";
|
|
13213
13263
|
var RULES_OUTPUT_ROOT = ".claude/rules";
|
|
13214
|
-
var TARGET_NATIVE_SOURCE_DIR = "src";
|
|
13215
13264
|
var PROJECT_AGENTS_DIR = "agents";
|
|
13265
|
+
var PROVIDER_SOURCE_DIRS = {
|
|
13266
|
+
claude: "_claude",
|
|
13267
|
+
codex: "_codex"
|
|
13268
|
+
};
|
|
13216
13269
|
var PLUGIN_FEATURE_KEYS = ["bin", "mcp"];
|
|
13217
13270
|
async function loadBuildGraph(rootPath, options = {}) {
|
|
13218
13271
|
const sourceDir = options.sourceDir ?? DEFAULT_SOURCE_DIR;
|
|
13219
13272
|
const sourcePath = resolveInside(rootPath, sourceDir);
|
|
13220
13273
|
const rootConfigPath = join8(sourcePath, ROOT_CONFIG_FILE);
|
|
13274
|
+
const rootSourceManifestPath = join8(sourcePath, SOURCE_ROOT_DIR, ROOT_SOURCE_MANIFEST_FILE);
|
|
13221
13275
|
const rootConfig = parseYamlRecord(await readFile7(rootConfigPath, "utf8"), rootConfigPath);
|
|
13222
|
-
|
|
13223
|
-
const
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13276
|
+
validateWorkspaceConfigDocument(rootConfig, rootConfigPath);
|
|
13277
|
+
const sourceManifest = parseYamlRecord(await readFile7(rootSourceManifestPath, "utf8"), rootSourceManifestPath);
|
|
13278
|
+
validateRootSourceManifestDocument(sourceManifest, rootSourceManifestPath);
|
|
13279
|
+
const metadata = readSkillsetMetadata(sourceManifest, rootSourceManifestPath);
|
|
13280
|
+
validateSchemaField(metadata, `${rootSourceManifestPath}.skillset.schema`);
|
|
13281
|
+
validateVersionField(metadata, `${rootSourceManifestPath}.skillset.version`);
|
|
13282
|
+
readSkillsetName(metadata, basename2(rootPath), rootSourceManifestPath);
|
|
13283
|
+
const outputs = readOutputConfig(rootConfig, {}, options.distDir === undefined ? {} : { distDir: options.distDir });
|
|
13228
13284
|
const distributions = readDistributionConfig(rootConfig, rootConfigPath);
|
|
13229
13285
|
const rootTargets = resolveTargets(readCompileTargets(rootConfig, rootConfigPath), rootConfig, rootConfigPath, {
|
|
13230
13286
|
allowDefaults: true,
|
|
@@ -13245,7 +13301,8 @@ async function loadBuildGraph(rootPath, options = {}) {
|
|
|
13245
13301
|
targets: filteredTargets
|
|
13246
13302
|
};
|
|
13247
13303
|
const warnings = [];
|
|
13248
|
-
await
|
|
13304
|
+
await rejectLegacySourceLayout(rootPath, sourceDir);
|
|
13305
|
+
await validateSupports(sourceManifest.supports, { label: rootSourceManifestPath, rootPath, warnings });
|
|
13249
13306
|
const releaseState = await readReleaseState(rootPath, options);
|
|
13250
13307
|
const plugins = await loadPlugins(rootPath, sourceDir, filteredTargets, warnings, outputs);
|
|
13251
13308
|
try {
|
|
@@ -13254,7 +13311,7 @@ async function loadBuildGraph(rootPath, options = {}) {
|
|
|
13254
13311
|
throw featureDiagnosticError(error, {
|
|
13255
13312
|
code: "plugin-dependencies-invalid",
|
|
13256
13313
|
featureId: "dependencies",
|
|
13257
|
-
path: join8(sourceDir, PLUGINS_DIR)
|
|
13314
|
+
path: join8(sourceDir, SOURCE_ROOT_DIR, PLUGINS_DIR)
|
|
13258
13315
|
});
|
|
13259
13316
|
}
|
|
13260
13317
|
const standaloneSkills = await loadStandaloneSkills(rootPath, sourceDir, filteredTargets, warnings);
|
|
@@ -13262,7 +13319,7 @@ async function loadBuildGraph(rootPath, options = {}) {
|
|
|
13262
13319
|
const projectAgents = await loadProjectAgents(rootPath, sourceDir, filteredTargets, warnings);
|
|
13263
13320
|
const projectIslands = await loadProjectIslands(rootPath, sourceDir, plugins);
|
|
13264
13321
|
if (plugins.length === 0 && standaloneSkills.length === 0 && rules.length === 0 && projectAgents.length === 0 && projectIslands.length === 0) {
|
|
13265
|
-
throw new Error(`skillset: no source plugins, skills,
|
|
13322
|
+
throw new Error(`skillset: no source plugins, skills, rules, project agents, or provider source found under ${sourceDir}/${SOURCE_ROOT_DIR}/`);
|
|
13266
13323
|
}
|
|
13267
13324
|
const outputRoots = await outputRootsFor(rootPath, outputs, plugins, standaloneSkills, rules);
|
|
13268
13325
|
validateOutputRoots(rootPath, sourcePath, outputRoots);
|
|
@@ -13307,20 +13364,52 @@ function featureDiagnosticError(error, args) {
|
|
|
13307
13364
|
...args.path === undefined ? {} : { path: args.path }
|
|
13308
13365
|
});
|
|
13309
13366
|
}
|
|
13367
|
+
async function rejectLegacySourceLayout(rootPath, sourceDir) {
|
|
13368
|
+
const moves = [
|
|
13369
|
+
["instructions", `${SOURCE_ROOT_DIR}/${RULES_DIR}`],
|
|
13370
|
+
["rules", `${SOURCE_ROOT_DIR}/${RULES_DIR}`],
|
|
13371
|
+
[SKILLS_DIR, `${SOURCE_ROOT_DIR}/${SKILLS_DIR}`],
|
|
13372
|
+
[PLUGINS_DIR, `${SOURCE_ROOT_DIR}/${PLUGINS_DIR}`],
|
|
13373
|
+
[SHARED_DIR, `${SOURCE_ROOT_DIR}/${SHARED_DIR}`],
|
|
13374
|
+
[`${SOURCE_ROOT_DIR}/claude`, `${SOURCE_ROOT_DIR}/${PROVIDER_SOURCE_DIRS.claude}`],
|
|
13375
|
+
[`${SOURCE_ROOT_DIR}/codex`, `${SOURCE_ROOT_DIR}/${PROVIDER_SOURCE_DIRS.codex}`]
|
|
13376
|
+
];
|
|
13377
|
+
for (const [oldPath, newPath] of moves) {
|
|
13378
|
+
const absoluteOldPath = resolveInside(rootPath, join8(sourceDir, oldPath));
|
|
13379
|
+
if (await exists5(absoluteOldPath)) {
|
|
13380
|
+
throw new Error(`skillset: ${join8(sourceDir, oldPath)} uses the retired source layout; move it to ${join8(sourceDir, newPath)}`);
|
|
13381
|
+
}
|
|
13382
|
+
}
|
|
13383
|
+
const pluginsPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, PLUGINS_DIR));
|
|
13384
|
+
if (!await exists5(pluginsPath))
|
|
13385
|
+
return;
|
|
13386
|
+
for (const entry of await readdir3(pluginsPath, { withFileTypes: true })) {
|
|
13387
|
+
if (!entry.isDirectory())
|
|
13388
|
+
continue;
|
|
13389
|
+
for (const [oldProviderDir, newProviderDir] of Object.entries(PROVIDER_SOURCE_DIRS)) {
|
|
13390
|
+
const oldPath = join8(SOURCE_ROOT_DIR, PLUGINS_DIR, entry.name, oldProviderDir);
|
|
13391
|
+
const absoluteOldPath = resolveInside(rootPath, join8(sourceDir, oldPath));
|
|
13392
|
+
if (!await exists5(absoluteOldPath))
|
|
13393
|
+
continue;
|
|
13394
|
+
const newPath = join8(SOURCE_ROOT_DIR, PLUGINS_DIR, entry.name, newProviderDir);
|
|
13395
|
+
throw new Error(`skillset: ${join8(sourceDir, oldPath)} uses the retired provider source layout; move it to ${join8(sourceDir, newPath)}`);
|
|
13396
|
+
}
|
|
13397
|
+
}
|
|
13398
|
+
}
|
|
13310
13399
|
async function loadProjectIslands(rootPath, sourceDir, plugins) {
|
|
13311
|
-
const srcPath = resolveInside(rootPath, join8(sourceDir,
|
|
13400
|
+
const srcPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR));
|
|
13312
13401
|
if (!await exists5(srcPath))
|
|
13313
13402
|
return [];
|
|
13314
13403
|
const islands = [];
|
|
13315
|
-
islands.push(...await loadTargetIsland(rootPath, join8(srcPath,
|
|
13316
|
-
islands.push(...await loadTargetIsland(rootPath, join8(srcPath,
|
|
13404
|
+
islands.push(...await loadTargetIsland(rootPath, join8(srcPath, PROVIDER_SOURCE_DIRS.claude), "claude"));
|
|
13405
|
+
islands.push(...await loadTargetIsland(rootPath, join8(srcPath, PROVIDER_SOURCE_DIRS.codex), "codex"));
|
|
13317
13406
|
const pluginsPath = join8(srcPath, "plugins");
|
|
13318
13407
|
if (await exists5(pluginsPath)) {
|
|
13319
13408
|
await validatePluginIslandOwners(rootPath, pluginsPath, plugins);
|
|
13320
13409
|
for (const plugin of plugins) {
|
|
13321
13410
|
const pluginPath = join8(pluginsPath, plugin.id);
|
|
13322
|
-
islands.push(...await loadTargetIsland(rootPath, join8(pluginPath,
|
|
13323
|
-
islands.push(...await loadTargetIsland(rootPath, join8(pluginPath,
|
|
13411
|
+
islands.push(...await loadTargetIsland(rootPath, join8(pluginPath, PROVIDER_SOURCE_DIRS.claude), "claude", plugin.id));
|
|
13412
|
+
islands.push(...await loadTargetIsland(rootPath, join8(pluginPath, PROVIDER_SOURCE_DIRS.codex), "codex", plugin.id));
|
|
13324
13413
|
}
|
|
13325
13414
|
}
|
|
13326
13415
|
for (const island of islands) {
|
|
@@ -13338,7 +13427,7 @@ async function loadProjectIslands(rootPath, sourceDir, plugins) {
|
|
|
13338
13427
|
throw new SkillsetFeatureDiagnosticError({
|
|
13339
13428
|
code: "target-native-island-unsupported",
|
|
13340
13429
|
featureId: "target-native-islands",
|
|
13341
|
-
message: `skillset: ${path} targets Codex .rules outside .skillset/src/
|
|
13430
|
+
message: `skillset: ${path} targets Codex .rules outside .skillset/src/_codex/rules/; ` + "Codex .rules are project-only command policy",
|
|
13342
13431
|
path
|
|
13343
13432
|
});
|
|
13344
13433
|
}
|
|
@@ -13367,7 +13456,7 @@ async function loadTargetIsland(rootPath, islandPath, target, plugin) {
|
|
|
13367
13456
|
}));
|
|
13368
13457
|
}
|
|
13369
13458
|
async function loadProjectAgents(rootPath, sourceDir, rootTargets, warnings) {
|
|
13370
|
-
const agentsPath = resolveInside(rootPath, join8(sourceDir,
|
|
13459
|
+
const agentsPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, PROJECT_AGENTS_DIR));
|
|
13371
13460
|
if (!await exists5(agentsPath))
|
|
13372
13461
|
return [];
|
|
13373
13462
|
const entries = await readdir3(agentsPath, { withFileTypes: true });
|
|
@@ -13449,15 +13538,10 @@ function validateProjectAgentCollisions(agents) {
|
|
|
13449
13538
|
}
|
|
13450
13539
|
}
|
|
13451
13540
|
async function loadInstructions(rootPath, sourceDir, rootTargets, warnings) {
|
|
13452
|
-
const canonicalPath = resolveInside(rootPath, join8(sourceDir,
|
|
13541
|
+
const canonicalPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, RULES_DIR));
|
|
13453
13542
|
const canonicalFiles = await exists5(canonicalPath) ? await findMarkdownFiles(canonicalPath) : [];
|
|
13454
|
-
const rulesPath = resolveInside(rootPath, join8(sourceDir, "rules"));
|
|
13455
|
-
const rulesFiles = await exists5(rulesPath) ? await findMarkdownFiles(rulesPath) : [];
|
|
13456
|
-
if (rulesFiles.length > 0) {
|
|
13457
|
-
throw new Error(`skillset: ${sourceDir}/rules is not supported; move instruction files to ${sourceDir}/${INSTRUCTIONS_DIR}`);
|
|
13458
|
-
}
|
|
13459
13543
|
if (canonicalFiles.length === 0) {
|
|
13460
|
-
return { rules: [], instructionsDir:
|
|
13544
|
+
return { rules: [], instructionsDir: join8(SOURCE_ROOT_DIR, RULES_DIR) };
|
|
13461
13545
|
}
|
|
13462
13546
|
const ruleFiles = canonicalFiles;
|
|
13463
13547
|
const rules = [];
|
|
@@ -13484,7 +13568,7 @@ async function loadInstructions(rootPath, sourceDir, rootTargets, warnings) {
|
|
|
13484
13568
|
}
|
|
13485
13569
|
return {
|
|
13486
13570
|
rules: rules.sort((left, right) => compareStrings(left.relativePath, right.relativePath)),
|
|
13487
|
-
instructionsDir:
|
|
13571
|
+
instructionsDir: join8(SOURCE_ROOT_DIR, RULES_DIR)
|
|
13488
13572
|
};
|
|
13489
13573
|
}
|
|
13490
13574
|
function readDialect(frontmatter, label) {
|
|
@@ -13503,7 +13587,7 @@ function normalizeRuleFrontmatter(frontmatter, label) {
|
|
|
13503
13587
|
return frontmatter;
|
|
13504
13588
|
}
|
|
13505
13589
|
async function loadPlugins(rootPath, sourceDir, rootTargets, warnings, outputs) {
|
|
13506
|
-
const pluginsPath = resolveInside(rootPath, join8(sourceDir, PLUGINS_DIR));
|
|
13590
|
+
const pluginsPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, PLUGINS_DIR));
|
|
13507
13591
|
if (!await exists5(pluginsPath))
|
|
13508
13592
|
return [];
|
|
13509
13593
|
const entries = await readdir3(pluginsPath, { withFileTypes: true });
|
|
@@ -13517,7 +13601,7 @@ async function loadPlugins(rootPath, sourceDir, rootTargets, warnings, outputs)
|
|
|
13517
13601
|
return plugins;
|
|
13518
13602
|
}
|
|
13519
13603
|
async function loadPlugin(rootPath, sourceDir, id, parentTargets, warnings, outputs) {
|
|
13520
|
-
const pluginPath = resolveInside(rootPath, join8(sourceDir, PLUGINS_DIR, id));
|
|
13604
|
+
const pluginPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, PLUGINS_DIR, id));
|
|
13521
13605
|
const configPath = await resolvePluginConfigPath(pluginPath);
|
|
13522
13606
|
const configRelativePath = relative8(rootPath, configPath);
|
|
13523
13607
|
const config = parseYamlRecord(await readFile7(configPath, "utf8"), configPath);
|
|
@@ -13700,7 +13784,7 @@ async function loadSkillsFromDirectory(rootPath, sourceDir, skillsPath, relative
|
|
|
13700
13784
|
const resources = await readSkillResources(parts.frontmatter.resources, {
|
|
13701
13785
|
label: sourcePath,
|
|
13702
13786
|
...pluginPath === undefined ? {} : { pluginSharedPath: join8(pluginPath, "shared") },
|
|
13703
|
-
sharedPath: resolveInside(rootPath, join8(sourceDir,
|
|
13787
|
+
sharedPath: resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, SHARED_DIR))
|
|
13704
13788
|
});
|
|
13705
13789
|
const dialect = readDialect(parts.frontmatter, relative8(rootPath, sourcePath));
|
|
13706
13790
|
skills.push({
|
|
@@ -13719,7 +13803,7 @@ async function loadSkillsFromDirectory(rootPath, sourceDir, skillsPath, relative
|
|
|
13719
13803
|
return skills.sort((left, right) => compareStrings(left.relativePath, right.relativePath));
|
|
13720
13804
|
}
|
|
13721
13805
|
async function loadStandaloneSkills(rootPath, sourceDir, rootTargets, warnings) {
|
|
13722
|
-
const skillsPath = resolveInside(rootPath, join8(sourceDir, SKILLS_DIR));
|
|
13806
|
+
const skillsPath = resolveInside(rootPath, join8(sourceDir, SOURCE_ROOT_DIR, SKILLS_DIR));
|
|
13723
13807
|
if (!await exists5(skillsPath))
|
|
13724
13808
|
return [];
|
|
13725
13809
|
const skills = await loadSkillsFromDirectory(rootPath, sourceDir, skillsPath, skillsPath, rootTargets, warnings);
|
|
@@ -13969,17 +14053,17 @@ async function buildSkillsetResult(rootPath, options = {}) {
|
|
|
13969
14053
|
const outPath = outPathMapper(options);
|
|
13970
14054
|
const allRendered = await renderBuildGraph(graph);
|
|
13971
14055
|
const scopedRendered = scopedRenderedFiles(graph, allRendered, options.scopes);
|
|
13972
|
-
const
|
|
14056
|
+
const renderResults = collectRenderResults(graph, allRendered, {
|
|
13973
14057
|
includedPaths: new Set(scopedRendered.map((file) => file.path)),
|
|
13974
14058
|
mapOutputPath: outPath,
|
|
13975
14059
|
scopes: options.scopes
|
|
13976
14060
|
});
|
|
13977
|
-
|
|
14061
|
+
enforceRenderResultPolicy(renderResults, graph.root.compile.unsupportedDestination);
|
|
13978
14062
|
const renderedWithoutOutcomeMetadata = mirroredRenderedFiles(scopedRendered, outPath);
|
|
13979
14063
|
const instructionDiagnostics = diagnoseLargeInstructionFiles(renderedWithoutOutcomeMetadata);
|
|
13980
14064
|
diagnostics.push(...instructionDiagnostics);
|
|
13981
|
-
const
|
|
13982
|
-
const rendered =
|
|
14065
|
+
const renderResultsWithDiagnostics = attachDiagnosticsToRenderResults(renderResults, instructionDiagnostics);
|
|
14066
|
+
const rendered = withPersistedRenderResults(renderedWithoutOutcomeMetadata, renderResultsWithDiagnostics);
|
|
13983
14067
|
const liveOutputRoots = scopedOutputRoots(graph, options.scopes);
|
|
13984
14068
|
const outputRoots = mirroredOutputRoots(liveOutputRoots, outPath);
|
|
13985
14069
|
const includeWorkspaceLock = includesProjectScope(options.scopes);
|
|
@@ -13992,7 +14076,7 @@ async function buildSkillsetResult(rootPath, options = {}) {
|
|
|
13992
14076
|
diagnostics.push(...safety2.diagnostics);
|
|
13993
14077
|
const deletedPaths2 = await removeStaleGeneratedFiles(rootPath, new Set(staleManagedPaths2), expectedPaths);
|
|
13994
14078
|
const writtenPaths2 = await writeRenderedFiles(rootPath, rendered);
|
|
13995
|
-
return buildResult(rendered, diagnostics,
|
|
14079
|
+
return buildResult(rendered, diagnostics, renderResultsWithDiagnostics, withBackupSummary(writeSummary(writtenPaths2, deletedPaths2), safety2.backup));
|
|
13996
14080
|
}
|
|
13997
14081
|
const actualPaths = new Set(await listGeneratedFiles(rootPath, outputRoots, rendered, previousManagedState.paths));
|
|
13998
14082
|
const staleManagedPaths = staleManagedOutputPaths(previousManagedState.paths, expectedPaths).filter((path) => actualPaths.has(path));
|
|
@@ -14000,7 +14084,7 @@ async function buildSkillsetResult(rootPath, options = {}) {
|
|
|
14000
14084
|
diagnostics.push(...safety.diagnostics);
|
|
14001
14085
|
const deletedPaths = await removeStaleGeneratedFiles(rootPath, new Set(staleManagedPaths), expectedPaths);
|
|
14002
14086
|
const writtenPaths = await writeChangedRenderedFiles(rootPath, rendered, actualPaths);
|
|
14003
|
-
return buildResult(rendered, diagnostics,
|
|
14087
|
+
return buildResult(rendered, diagnostics, renderResultsWithDiagnostics, withBackupSummary(writeSummary(writtenPaths, deletedPaths), safety.backup));
|
|
14004
14088
|
}
|
|
14005
14089
|
async function diffSkillset(rootPath, options = {}) {
|
|
14006
14090
|
return (await diffSkillsetResult(rootPath, options)).data;
|
|
@@ -14011,17 +14095,17 @@ async function diffSkillsetResult(rootPath, options = {}) {
|
|
|
14011
14095
|
const outPath = outPathMapper(options);
|
|
14012
14096
|
const allRendered = await renderBuildGraph(graph);
|
|
14013
14097
|
const scopedRendered = scopedRenderedFiles(graph, allRendered, options.scopes);
|
|
14014
|
-
const
|
|
14098
|
+
const renderResults = collectRenderResults(graph, allRendered, {
|
|
14015
14099
|
includedPaths: new Set(scopedRendered.map((file) => file.path)),
|
|
14016
14100
|
mapOutputPath: outPath,
|
|
14017
14101
|
scopes: options.scopes
|
|
14018
14102
|
});
|
|
14019
|
-
|
|
14103
|
+
enforceRenderResultPolicy(renderResults, graph.root.compile.unsupportedDestination);
|
|
14020
14104
|
const renderedWithoutOutcomeMetadata = mirroredRenderedFiles(scopedRendered, outPath);
|
|
14021
14105
|
const instructionDiagnostics = diagnoseLargeInstructionFiles(renderedWithoutOutcomeMetadata);
|
|
14022
14106
|
diagnostics.push(...instructionDiagnostics);
|
|
14023
|
-
const
|
|
14024
|
-
const rendered =
|
|
14107
|
+
const renderResultsWithDiagnostics = attachDiagnosticsToRenderResults(renderResults, instructionDiagnostics);
|
|
14108
|
+
const rendered = withPersistedRenderResults(renderedWithoutOutcomeMetadata, renderResultsWithDiagnostics);
|
|
14025
14109
|
const expected = new Map(rendered.map((file) => [file.path, file.content]));
|
|
14026
14110
|
const liveOutputRoots = scopedOutputRoots(graph, options.scopes);
|
|
14027
14111
|
const outputRoots = mirroredOutputRoots(liveOutputRoots, outPath);
|
|
@@ -14063,7 +14147,7 @@ async function diffSkillsetResult(rootPath, options = {}) {
|
|
|
14063
14147
|
return {
|
|
14064
14148
|
data: diff,
|
|
14065
14149
|
diagnostics,
|
|
14066
|
-
|
|
14150
|
+
renderResults: renderResultsWithDiagnostics,
|
|
14067
14151
|
ok: true,
|
|
14068
14152
|
operation: "diff",
|
|
14069
14153
|
writes: {
|
|
@@ -14080,17 +14164,17 @@ async function checkSkillsetResult(rootPath, options = {}) {
|
|
|
14080
14164
|
const outPath = outPathMapper(options);
|
|
14081
14165
|
const allRendered = await renderBuildGraph(graph);
|
|
14082
14166
|
const scopedRendered = scopedRenderedFiles(graph, allRendered, options.scopes);
|
|
14083
|
-
const
|
|
14167
|
+
const renderResults = collectRenderResults(graph, allRendered, {
|
|
14084
14168
|
includedPaths: new Set(scopedRendered.map((file) => file.path)),
|
|
14085
14169
|
mapOutputPath: outPath,
|
|
14086
14170
|
scopes: options.scopes
|
|
14087
14171
|
});
|
|
14088
|
-
|
|
14172
|
+
enforceRenderResultPolicy(renderResults, graph.root.compile.unsupportedDestination);
|
|
14089
14173
|
const renderedWithoutOutcomeMetadata = mirroredRenderedFiles(scopedRendered, outPath);
|
|
14090
14174
|
const instructionDiagnostics = diagnoseLargeInstructionFiles(renderedWithoutOutcomeMetadata);
|
|
14091
14175
|
diagnostics.push(...instructionDiagnostics);
|
|
14092
|
-
const
|
|
14093
|
-
const rendered =
|
|
14176
|
+
const renderResultsWithDiagnostics = attachDiagnosticsToRenderResults(renderResults, instructionDiagnostics);
|
|
14177
|
+
const rendered = withPersistedRenderResults(renderedWithoutOutcomeMetadata, renderResultsWithDiagnostics);
|
|
14094
14178
|
const expected = new Map(rendered.map((file) => [file.path, file.content]));
|
|
14095
14179
|
const liveOutputRoots = scopedOutputRoots(graph, options.scopes);
|
|
14096
14180
|
const outputRoots = mirroredOutputRoots(liveOutputRoots, outPath);
|
|
@@ -14125,7 +14209,7 @@ async function checkSkillsetResult(rootPath, options = {}) {
|
|
|
14125
14209
|
return {
|
|
14126
14210
|
data: { checkedFiles: rendered.length, failures },
|
|
14127
14211
|
diagnostics: [...diagnostics, ...driftDiagnostics],
|
|
14128
|
-
|
|
14212
|
+
renderResults: renderResultsWithDiagnostics,
|
|
14129
14213
|
ok: failures.length === 0,
|
|
14130
14214
|
operation: "check",
|
|
14131
14215
|
writes: {
|
|
@@ -14153,21 +14237,21 @@ function generatedDriftMessage(kind, path) {
|
|
|
14153
14237
|
return `missing managed generated file: ${path}`;
|
|
14154
14238
|
return `stale generated file: ${path}`;
|
|
14155
14239
|
}
|
|
14156
|
-
function buildResult(rendered, diagnostics,
|
|
14240
|
+
function buildResult(rendered, diagnostics, renderResults, writes) {
|
|
14157
14241
|
return {
|
|
14158
14242
|
data: rendered,
|
|
14159
14243
|
diagnostics,
|
|
14160
|
-
|
|
14244
|
+
renderResults,
|
|
14161
14245
|
ok: true,
|
|
14162
14246
|
operation: "build",
|
|
14163
14247
|
writes
|
|
14164
14248
|
};
|
|
14165
14249
|
}
|
|
14166
|
-
function
|
|
14250
|
+
function attachDiagnosticsToRenderResults(renderResults, diagnostics) {
|
|
14167
14251
|
const outputDiagnostics = diagnostics.filter((diagnostic) => diagnostic.outputPath !== undefined);
|
|
14168
14252
|
if (outputDiagnostics.length === 0)
|
|
14169
|
-
return
|
|
14170
|
-
return
|
|
14253
|
+
return renderResults;
|
|
14254
|
+
return renderResults.map((outcome) => {
|
|
14171
14255
|
const outputPaths = new Set((outcome.outputs ?? []).map((output) => output.path));
|
|
14172
14256
|
if (outputPaths.size === 0)
|
|
14173
14257
|
return outcome;
|
|
@@ -14180,7 +14264,7 @@ function attachDiagnosticsToLoweringOutcomes(loweringOutcomes, diagnostics) {
|
|
|
14180
14264
|
});
|
|
14181
14265
|
if (matching.length === 0)
|
|
14182
14266
|
return outcome;
|
|
14183
|
-
return
|
|
14267
|
+
return defineRenderResult({
|
|
14184
14268
|
...outcome,
|
|
14185
14269
|
diagnostics: [
|
|
14186
14270
|
...outcome.diagnostics ?? [],
|
|
@@ -14191,7 +14275,7 @@ function attachDiagnosticsToLoweringOutcomes(loweringOutcomes, diagnostics) {
|
|
|
14191
14275
|
}
|
|
14192
14276
|
function diagnosticRefForOutput(diagnostic) {
|
|
14193
14277
|
if (diagnostic.outputPath === undefined) {
|
|
14194
|
-
throw new Error("skillset:
|
|
14278
|
+
throw new Error("skillset: render result diagnostic ref requires an output path");
|
|
14195
14279
|
}
|
|
14196
14280
|
return {
|
|
14197
14281
|
code: diagnostic.code,
|
|
@@ -14199,17 +14283,17 @@ function diagnosticRefForOutput(diagnostic) {
|
|
|
14199
14283
|
path: diagnostic.outputPath
|
|
14200
14284
|
};
|
|
14201
14285
|
}
|
|
14202
|
-
function
|
|
14203
|
-
if (
|
|
14286
|
+
function withPersistedRenderResults(rendered, renderResults) {
|
|
14287
|
+
if (renderResults.length === 0)
|
|
14204
14288
|
return rendered;
|
|
14205
14289
|
return rendered.map((file) => {
|
|
14206
14290
|
if (!isLockFilePath(file.path))
|
|
14207
14291
|
return file;
|
|
14208
14292
|
const lock = parseLockFile(file);
|
|
14209
|
-
const lockOutcomes =
|
|
14293
|
+
const lockOutcomes = renderResultsForLock(file.path, lock, renderResults);
|
|
14210
14294
|
const value = {
|
|
14211
14295
|
...lock,
|
|
14212
|
-
...lockOutcomes.length === 0 ? {} : {
|
|
14296
|
+
...lockOutcomes.length === 0 ? {} : { renderResults: lockOutcomes }
|
|
14213
14297
|
};
|
|
14214
14298
|
return {
|
|
14215
14299
|
...file,
|
|
@@ -14224,11 +14308,11 @@ function parseLockFile(file) {
|
|
|
14224
14308
|
}
|
|
14225
14309
|
return parsed;
|
|
14226
14310
|
}
|
|
14227
|
-
function
|
|
14311
|
+
function renderResultsForLock(lockPath, lock, renderResults) {
|
|
14228
14312
|
const target = typeof lock.target === "string" ? lock.target : undefined;
|
|
14229
14313
|
const outputRoot = outputRootForLockPath(lockPath);
|
|
14230
14314
|
const lockOutputs = outputPathsForLock(outputRoot, lock);
|
|
14231
|
-
return
|
|
14315
|
+
return renderResults.filter((outcome) => {
|
|
14232
14316
|
if (target !== undefined && (outcome.target ?? "workspace") !== target)
|
|
14233
14317
|
return false;
|
|
14234
14318
|
const outputPaths = outcome.outputs?.map((output) => output.path) ?? [];
|
|
@@ -14236,7 +14320,7 @@ function loweringOutcomesForLock(lockPath, lock, loweringOutcomes) {
|
|
|
14236
14320
|
return outputRoot === "." && outcome.target === undefined;
|
|
14237
14321
|
}
|
|
14238
14322
|
return outputPaths.some((path) => lockOutputs.has(path));
|
|
14239
|
-
}).sort((left, right) => compareStrings(`${left.sourceUnit}\x00${left.target ?? ""}\x00${left.featureId}\x00${left.status}\x00${left.sourcePath ?? ""}`, `${right.sourceUnit}\x00${right.target ?? ""}\x00${right.featureId}\x00${right.status}\x00${right.sourcePath ?? ""}`));
|
|
14323
|
+
}).sort((left, right) => compareStrings(`${left.sourceUnit}\x00${left.target ?? ""}\x00${left.featureId}\x00${left.destination ?? ""}\x00${left.status}\x00${left.sourcePath ?? ""}`, `${right.sourceUnit}\x00${right.target ?? ""}\x00${right.featureId}\x00${right.destination ?? ""}\x00${right.status}\x00${right.sourcePath ?? ""}`));
|
|
14240
14324
|
}
|
|
14241
14325
|
function outputPathsForLock(outputRoot, lock) {
|
|
14242
14326
|
const items = Array.isArray(lock.items) ? lock.items : [];
|
|
@@ -15177,7 +15261,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
15177
15261
|
const graph = await loadBuildGraph(rootPath, options);
|
|
15178
15262
|
const allRendered = await renderBuildGraph(graph);
|
|
15179
15263
|
const rendered = scopedRenderedFiles(graph, allRendered, options.scopes);
|
|
15180
|
-
const
|
|
15264
|
+
const renderResults = collectRenderResults(graph, allRendered, {
|
|
15181
15265
|
includedPaths: new Set(rendered.map((file) => file.path)),
|
|
15182
15266
|
scopes: options.scopes
|
|
15183
15267
|
});
|
|
@@ -15185,51 +15269,51 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
15185
15269
|
const items = collectLockItems(rendered);
|
|
15186
15270
|
const asSource = items.filter((item) => item.sourcePath === target);
|
|
15187
15271
|
if (asSource.length > 0) {
|
|
15188
|
-
const
|
|
15272
|
+
const matchedRenderResults = explainRenderResults(target, asSource, renderResults);
|
|
15189
15273
|
return {
|
|
15190
15274
|
path: target,
|
|
15191
15275
|
kind: explainSourceKind(graph, target),
|
|
15192
15276
|
entries: asSource.map((item) => item.entry),
|
|
15193
|
-
features: featureCapabilitiesForPath(graph, target, asSource,
|
|
15194
|
-
|
|
15277
|
+
features: featureCapabilitiesForPath(graph, target, asSource, matchedRenderResults),
|
|
15278
|
+
renderResults: matchedRenderResults,
|
|
15195
15279
|
notes: sourceNotes(graph, target)
|
|
15196
15280
|
};
|
|
15197
15281
|
}
|
|
15198
15282
|
const asGenerated = items.filter((item) => item.outputPath === target || item.files.some((file) => joinOutputRoot2(item.outputRoot, file) === target));
|
|
15199
15283
|
if (asGenerated.length > 0) {
|
|
15200
|
-
const
|
|
15284
|
+
const matchedRenderResults = explainRenderResults(target, asGenerated, renderResults, {
|
|
15201
15285
|
includeSourcePaths: false
|
|
15202
15286
|
});
|
|
15203
15287
|
return {
|
|
15204
15288
|
path: target,
|
|
15205
15289
|
kind: "generated",
|
|
15206
15290
|
entries: asGenerated.map((item) => item.entry),
|
|
15207
|
-
features: featureCapabilitiesForPath(graph, target, asGenerated,
|
|
15208
|
-
|
|
15291
|
+
features: featureCapabilitiesForPath(graph, target, asGenerated, matchedRenderResults),
|
|
15292
|
+
renderResults: matchedRenderResults,
|
|
15209
15293
|
notes: [`Generated output; rebuild with skillset build, verify with skillset check.`]
|
|
15210
15294
|
};
|
|
15211
15295
|
}
|
|
15212
15296
|
const prefixMatch = items.filter((item) => item.sourcePath.startsWith(`${target}/`));
|
|
15213
15297
|
if (prefixMatch.length > 0) {
|
|
15214
|
-
const
|
|
15298
|
+
const matchedRenderResults = explainRenderResults(target, prefixMatch, renderResults);
|
|
15215
15299
|
return {
|
|
15216
15300
|
path: target,
|
|
15217
15301
|
kind: "source-plugin",
|
|
15218
15302
|
entries: prefixMatch.map((item) => item.entry),
|
|
15219
|
-
features: featureCapabilitiesForPath(graph, target, prefixMatch,
|
|
15220
|
-
|
|
15303
|
+
features: featureCapabilitiesForPath(graph, target, prefixMatch, matchedRenderResults),
|
|
15304
|
+
renderResults: matchedRenderResults,
|
|
15221
15305
|
notes: [`Matched ${prefixMatch.length} generated entries under this source path.`]
|
|
15222
15306
|
};
|
|
15223
15307
|
}
|
|
15224
|
-
const sourceOnlyOutcomes =
|
|
15308
|
+
const sourceOnlyOutcomes = explainRenderResults(target, [], renderResults);
|
|
15225
15309
|
if (sourceOnlyOutcomes.length > 0) {
|
|
15226
15310
|
return {
|
|
15227
15311
|
path: target,
|
|
15228
15312
|
kind: explainSourceKind(graph, target),
|
|
15229
15313
|
entries: [],
|
|
15230
15314
|
features: featureCapabilitiesForPath(graph, target, [], sourceOnlyOutcomes),
|
|
15231
|
-
|
|
15232
|
-
notes: [`Matched ${sourceOnlyOutcomes.length}
|
|
15315
|
+
renderResults: sourceOnlyOutcomes,
|
|
15316
|
+
notes: [`Matched ${sourceOnlyOutcomes.length} render result(s) under this source path.`]
|
|
15233
15317
|
};
|
|
15234
15318
|
}
|
|
15235
15319
|
return {
|
|
@@ -15237,7 +15321,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
15237
15321
|
kind: "unknown",
|
|
15238
15322
|
entries: [],
|
|
15239
15323
|
features: [],
|
|
15240
|
-
|
|
15324
|
+
renderResults: [],
|
|
15241
15325
|
notes: [
|
|
15242
15326
|
`No lock entry references ${target}. Pass a source path under ${graph.sourceDir}/ or a generated output path.`
|
|
15243
15327
|
]
|
|
@@ -15269,15 +15353,15 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
15269
15353
|
graph = await loadBuildGraph(rootPath, options);
|
|
15270
15354
|
} catch (error) {
|
|
15271
15355
|
const buildDiagnostics2 = diagnosticsFromError(error);
|
|
15272
|
-
const
|
|
15356
|
+
const renderResults2 = renderResultsFromError(error);
|
|
15273
15357
|
return {
|
|
15274
15358
|
buildError: errorMessage(error),
|
|
15275
15359
|
buildDiagnostics: buildDiagnostics2,
|
|
15276
15360
|
drift: { added: [], changed: [], missing: [], removed: [] },
|
|
15277
15361
|
featureCapabilities: summarizeFeatureCapabilities(),
|
|
15278
15362
|
lintIssues: [],
|
|
15279
|
-
|
|
15280
|
-
|
|
15363
|
+
renderResults: renderResults2,
|
|
15364
|
+
notableRenderResults: notableRenderResults(renderResults2),
|
|
15281
15365
|
ok: false,
|
|
15282
15366
|
warnings: []
|
|
15283
15367
|
};
|
|
@@ -15286,31 +15370,31 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
15286
15370
|
let drift = { added: [], changed: [], missing: [], removed: [] };
|
|
15287
15371
|
let buildDiagnostics = [];
|
|
15288
15372
|
let buildError;
|
|
15289
|
-
let
|
|
15373
|
+
let renderResults = [];
|
|
15290
15374
|
try {
|
|
15291
15375
|
const diff = await diffSkillsetResult(rootPath, options);
|
|
15292
15376
|
drift = diff.data;
|
|
15293
|
-
|
|
15377
|
+
renderResults = diff.renderResults;
|
|
15294
15378
|
} catch (error) {
|
|
15295
15379
|
buildDiagnostics = diagnosticsFromError(error);
|
|
15296
15380
|
buildError = errorMessage(error);
|
|
15297
|
-
|
|
15381
|
+
renderResults = renderResultsFromError(error);
|
|
15298
15382
|
}
|
|
15299
15383
|
const hasDrift = drift.added.length > 0 || drift.changed.length > 0 || drift.missing.length > 0 || drift.removed.length > 0;
|
|
15300
|
-
const notable =
|
|
15384
|
+
const notable = notableRenderResults(renderResults);
|
|
15301
15385
|
return {
|
|
15302
15386
|
...buildError === undefined ? {} : { buildError },
|
|
15303
15387
|
buildDiagnostics,
|
|
15304
15388
|
drift,
|
|
15305
15389
|
featureCapabilities: summarizeFeatureCapabilities(),
|
|
15306
15390
|
lintIssues: lint.issues,
|
|
15307
|
-
|
|
15308
|
-
|
|
15391
|
+
renderResults,
|
|
15392
|
+
notableRenderResults: notable,
|
|
15309
15393
|
ok: lint.issues.length === 0 && !hasDrift && buildError === undefined,
|
|
15310
15394
|
warnings: graph.warnings
|
|
15311
15395
|
};
|
|
15312
15396
|
}
|
|
15313
|
-
function
|
|
15397
|
+
function explainRenderResults(target, items, outcomes, options = {}) {
|
|
15314
15398
|
const includeSourcePaths = options.includeSourcePaths !== false;
|
|
15315
15399
|
const itemSourcePaths = new Set(items.map((item) => item.sourcePath));
|
|
15316
15400
|
const itemOutputPaths = new Set(items.flatMap((item) => [
|
|
@@ -15334,11 +15418,11 @@ function explainLoweringOutcomes(target, items, outcomes, options = {}) {
|
|
|
15334
15418
|
}
|
|
15335
15419
|
return matched;
|
|
15336
15420
|
}
|
|
15337
|
-
function
|
|
15421
|
+
function notableRenderResults(outcomes) {
|
|
15338
15422
|
return outcomes.filter((outcome) => outcome.status === "degraded" || outcome.status === "externally_managed" || outcome.status === "failed" || outcome.status === "intentionally_skipped" || outcome.status === "lossy" || outcome.status === "unsupported").sort((left, right) => compareStrings(`${left.target ?? "workspace"}\x00${left.sourceUnit}\x00${left.featureId}\x00${left.status}`, `${right.target ?? "workspace"}\x00${right.sourceUnit}\x00${right.featureId}\x00${right.status}`));
|
|
15339
15423
|
}
|
|
15340
|
-
function
|
|
15341
|
-
return error instanceof
|
|
15424
|
+
function renderResultsFromError(error) {
|
|
15425
|
+
return error instanceof SkillsetRenderResultError ? error.renderResults : [];
|
|
15342
15426
|
}
|
|
15343
15427
|
function diagnosticsFromError(error) {
|
|
15344
15428
|
if (!(error instanceof SkillsetFeatureDiagnosticError))
|
|
@@ -16171,7 +16255,7 @@ import { join as join13 } from "path";
|
|
|
16171
16255
|
|
|
16172
16256
|
// apps/skillset/src/change-status.ts
|
|
16173
16257
|
import { createHash as createHash5 } from "crypto";
|
|
16174
|
-
import { mkdtemp, readFile as readFile12, rm as rm2, stat as stat9 } from "fs/promises";
|
|
16258
|
+
import { mkdir as mkdir4, mkdtemp, readdir as readdir5, readFile as readFile12, rename, rm as rm2, stat as stat9, writeFile as writeFile4 } from "fs/promises";
|
|
16175
16259
|
import { tmpdir } from "os";
|
|
16176
16260
|
import { dirname as dirname9, join as join12, relative as relative12 } from "path";
|
|
16177
16261
|
// apps/skillset/src/git-env.ts
|
|
@@ -16191,6 +16275,17 @@ function gitSafeEnv(sourceEnv = process.env) {
|
|
|
16191
16275
|
// apps/skillset/src/change-status.ts
|
|
16192
16276
|
var SOURCE_HASH_SCHEMA = "skillset-source-unit-v2";
|
|
16193
16277
|
var ROOT_CONFIG_FILE2 = "config.yaml";
|
|
16278
|
+
var SOURCE_ROOT_DIR2 = "src";
|
|
16279
|
+
var ROOT_SOURCE_MANIFEST_FILE2 = "skillset.yaml";
|
|
16280
|
+
var LEGACY_BASELINE_SOURCE_MOVES = [
|
|
16281
|
+
["instructions", "src/rules"],
|
|
16282
|
+
["rules", "src/rules"],
|
|
16283
|
+
["skills", "src/skills"],
|
|
16284
|
+
["plugins", "src/plugins"],
|
|
16285
|
+
["shared", "src/shared"],
|
|
16286
|
+
["src/claude", "src/_claude"],
|
|
16287
|
+
["src/codex", "src/_codex"]
|
|
16288
|
+
];
|
|
16194
16289
|
var PLUGIN_COMPANION_PATHS = [
|
|
16195
16290
|
"README.md",
|
|
16196
16291
|
"commands",
|
|
@@ -16229,8 +16324,7 @@ async function collectSourceInventory(rootPath, options = {}) {
|
|
|
16229
16324
|
}
|
|
16230
16325
|
async function sourceInventoryForGraph(graph) {
|
|
16231
16326
|
const units = [];
|
|
16232
|
-
|
|
16233
|
-
units.push(await fileUnit(graph, "root-config", selectorForRootConfig(), rootConfigPath, await regionsForYaml(rootConfigPath), "root-config"));
|
|
16327
|
+
units.push(await rootConfigUnit(graph));
|
|
16234
16328
|
for (const skill of graph.standaloneSkills) {
|
|
16235
16329
|
units.push(await skillUnit(graph, skill, "standalone-skill", selectorForStandaloneSkill(skill.id)));
|
|
16236
16330
|
}
|
|
@@ -16264,6 +16358,30 @@ async function sourceInventoryForGraph(graph) {
|
|
|
16264
16358
|
units: [...dedupeUnits(units)].sort((left, right) => compareStrings(left.id, right.id))
|
|
16265
16359
|
};
|
|
16266
16360
|
}
|
|
16361
|
+
async function rootConfigUnit(graph) {
|
|
16362
|
+
const configPath = join12(graph.sourcePath, ROOT_CONFIG_FILE2);
|
|
16363
|
+
const manifestPath = join12(graph.sourcePath, SOURCE_ROOT_DIR2, ROOT_SOURCE_MANIFEST_FILE2);
|
|
16364
|
+
const sourcePaths = [relativePath(graph, configPath), relativePath(graph, manifestPath)];
|
|
16365
|
+
const hash = createSourceHash("root-config");
|
|
16366
|
+
hash.update("metadata\x00");
|
|
16367
|
+
hash.update(stringifyJson({ id: "root-config", sourcePaths }));
|
|
16368
|
+
hash.update("\x00config\x00");
|
|
16369
|
+
await hashPathInto(hash, configPath);
|
|
16370
|
+
hash.update("\x00manifest\x00");
|
|
16371
|
+
await hashPathInto(hash, manifestPath);
|
|
16372
|
+
return {
|
|
16373
|
+
hash: digest(hash),
|
|
16374
|
+
hashSchema: SOURCE_HASH_SCHEMA,
|
|
16375
|
+
id: selectorForRootConfig(),
|
|
16376
|
+
kind: "root-config",
|
|
16377
|
+
regions: mergeRegions([
|
|
16378
|
+
...await regionsForYaml(configPath),
|
|
16379
|
+
...await regionsForYaml(manifestPath)
|
|
16380
|
+
]),
|
|
16381
|
+
sourcePath: sourcePaths[0] ?? "",
|
|
16382
|
+
sourcePaths
|
|
16383
|
+
};
|
|
16384
|
+
}
|
|
16267
16385
|
async function fileUnit(graph, kind, id, sourcePath, regions = [], hashId = id) {
|
|
16268
16386
|
const sourcePaths = [relativePath(graph, sourcePath)];
|
|
16269
16387
|
return {
|
|
@@ -16513,7 +16631,7 @@ async function skillPreprocessDependencies(graph, skill, plugin) {
|
|
|
16513
16631
|
preprocessDependencies: dependencies,
|
|
16514
16632
|
rootPath: graph.rootPath,
|
|
16515
16633
|
sourcePath: skill.sourcePath,
|
|
16516
|
-
sourceRoot: graph.sourceDir,
|
|
16634
|
+
sourceRoot: join12(graph.sourceDir, "src"),
|
|
16517
16635
|
...plugin === undefined ? {} : { pluginPath: plugin.path }
|
|
16518
16636
|
};
|
|
16519
16637
|
await preprocessText(skill.body, context);
|
|
@@ -16533,7 +16651,7 @@ async function rulePreprocessDependencies(graph, rule) {
|
|
|
16533
16651
|
preprocessDependencies: dependencies,
|
|
16534
16652
|
rootPath: graph.rootPath,
|
|
16535
16653
|
sourcePath: rule.sourcePath,
|
|
16536
|
-
sourceRoot: graph.sourceDir,
|
|
16654
|
+
sourceRoot: join12(graph.sourceDir, "src"),
|
|
16537
16655
|
variables: {
|
|
16538
16656
|
"skillset.output_dir": ".",
|
|
16539
16657
|
"skillset.repo_root": ".",
|
|
@@ -16552,7 +16670,7 @@ async function projectAgentPreprocessDependencies2(graph, agent) {
|
|
|
16552
16670
|
preprocessDependencies: dependencies,
|
|
16553
16671
|
rootPath: graph.rootPath,
|
|
16554
16672
|
sourcePath: agent.sourcePath,
|
|
16555
|
-
sourceRoot: graph.sourceDir
|
|
16673
|
+
sourceRoot: join12(graph.sourceDir, "src")
|
|
16556
16674
|
});
|
|
16557
16675
|
};
|
|
16558
16676
|
await collect(agent.body);
|
|
@@ -16574,7 +16692,7 @@ async function islandPreprocessDependencies(graph, island) {
|
|
|
16574
16692
|
preprocessDependencies: dependencies,
|
|
16575
16693
|
rootPath: graph.rootPath,
|
|
16576
16694
|
sourcePath: island.sourcePath,
|
|
16577
|
-
sourceRoot: graph.sourceDir
|
|
16695
|
+
sourceRoot: join12(graph.sourceDir, "src")
|
|
16578
16696
|
});
|
|
16579
16697
|
} else {
|
|
16580
16698
|
await preprocessText(source2, {
|
|
@@ -16582,7 +16700,7 @@ async function islandPreprocessDependencies(graph, island) {
|
|
|
16582
16700
|
preprocessDependencies: dependencies,
|
|
16583
16701
|
rootPath: graph.rootPath,
|
|
16584
16702
|
sourcePath: island.sourcePath,
|
|
16585
|
-
sourceRoot: graph.sourceDir
|
|
16703
|
+
sourceRoot: join12(graph.sourceDir, "src")
|
|
16586
16704
|
});
|
|
16587
16705
|
}
|
|
16588
16706
|
return [...dependencies].sort(compareStrings);
|
|
@@ -16683,6 +16801,7 @@ async function fallbackBaselineInventory(rootPath, options) {
|
|
|
16683
16801
|
async function inventoryFromGitRef(rootPath, ref, options) {
|
|
16684
16802
|
const snapshotPath = await snapshotGitRef(rootPath, ref);
|
|
16685
16803
|
try {
|
|
16804
|
+
await normalizeLegacyBaselineSnapshot(snapshotPath, options);
|
|
16686
16805
|
const inventory = await collectSourceInventory(snapshotPath, options);
|
|
16687
16806
|
const resolvedRef = await gitRevParse(rootPath, ref);
|
|
16688
16807
|
return {
|
|
@@ -16693,6 +16812,74 @@ async function inventoryFromGitRef(rootPath, ref, options) {
|
|
|
16693
16812
|
await rm2(snapshotPath, { force: true, recursive: true });
|
|
16694
16813
|
}
|
|
16695
16814
|
}
|
|
16815
|
+
async function normalizeLegacyBaselineSnapshot(snapshotPath, options) {
|
|
16816
|
+
const sourceDir = options.sourceDir ?? ".skillset";
|
|
16817
|
+
const skillsetPath = join12(snapshotPath, sourceDir);
|
|
16818
|
+
if (!await exists7(skillsetPath))
|
|
16819
|
+
return;
|
|
16820
|
+
for (const [from, to] of LEGACY_BASELINE_SOURCE_MOVES) {
|
|
16821
|
+
await moveLegacyBaselinePath(join12(skillsetPath, from), join12(skillsetPath, to));
|
|
16822
|
+
}
|
|
16823
|
+
await moveLegacyBaselinePluginProviderDirs(join12(skillsetPath, SOURCE_ROOT_DIR2, "plugins"));
|
|
16824
|
+
await splitLegacyBaselineRootConfig(skillsetPath);
|
|
16825
|
+
}
|
|
16826
|
+
async function moveLegacyBaselinePluginProviderDirs(pluginsPath) {
|
|
16827
|
+
if (!await exists7(pluginsPath))
|
|
16828
|
+
return;
|
|
16829
|
+
const entries = await readdir5(pluginsPath, { withFileTypes: true });
|
|
16830
|
+
for (const entry of entries) {
|
|
16831
|
+
if (!entry.isDirectory())
|
|
16832
|
+
continue;
|
|
16833
|
+
const pluginPath = join12(pluginsPath, entry.name);
|
|
16834
|
+
await moveLegacyBaselinePath(join12(pluginPath, "claude"), join12(pluginPath, "_claude"));
|
|
16835
|
+
await moveLegacyBaselinePath(join12(pluginPath, "codex"), join12(pluginPath, "_codex"));
|
|
16836
|
+
}
|
|
16837
|
+
}
|
|
16838
|
+
async function splitLegacyBaselineRootConfig(skillsetPath) {
|
|
16839
|
+
const configPath = join12(skillsetPath, ROOT_CONFIG_FILE2);
|
|
16840
|
+
if (!await exists7(configPath))
|
|
16841
|
+
return;
|
|
16842
|
+
const config2 = parseYamlRecord(await readFile12(configPath, "utf8"), configPath);
|
|
16843
|
+
const manifest = sourceManifestFromLegacyRootConfig(config2);
|
|
16844
|
+
if (manifest === undefined)
|
|
16845
|
+
return;
|
|
16846
|
+
const manifestPath = join12(skillsetPath, SOURCE_ROOT_DIR2, ROOT_SOURCE_MANIFEST_FILE2);
|
|
16847
|
+
if (await exists7(manifestPath)) {
|
|
16848
|
+
throw new Error(`skillset: cannot normalize baseline with both root source metadata and ${manifestPath}`);
|
|
16849
|
+
}
|
|
16850
|
+
await mkdir4(dirname9(manifestPath), { recursive: true });
|
|
16851
|
+
await writeFile4(manifestPath, stringifyYaml(manifest), "utf8");
|
|
16852
|
+
await writeFile4(configPath, stringifyLegacyWorkspaceConfig(workspaceConfigFromLegacyRootConfig(config2)), "utf8");
|
|
16853
|
+
}
|
|
16854
|
+
function sourceManifestFromLegacyRootConfig(record) {
|
|
16855
|
+
const manifest = {};
|
|
16856
|
+
if (isJsonRecord(record.skillset))
|
|
16857
|
+
manifest.skillset = record.skillset;
|
|
16858
|
+
if (record.supports !== undefined)
|
|
16859
|
+
manifest.supports = record.supports;
|
|
16860
|
+
return Object.keys(manifest).length === 0 ? undefined : manifest;
|
|
16861
|
+
}
|
|
16862
|
+
function workspaceConfigFromLegacyRootConfig(record) {
|
|
16863
|
+
const config2 = {};
|
|
16864
|
+
for (const [key, value] of Object.entries(record)) {
|
|
16865
|
+
if (key === "skillset" || key === "supports")
|
|
16866
|
+
continue;
|
|
16867
|
+
config2[key] = value;
|
|
16868
|
+
}
|
|
16869
|
+
return config2;
|
|
16870
|
+
}
|
|
16871
|
+
function stringifyLegacyWorkspaceConfig(record) {
|
|
16872
|
+
return Object.keys(record).length === 0 ? `
|
|
16873
|
+
` : stringifyYaml(record);
|
|
16874
|
+
}
|
|
16875
|
+
async function moveLegacyBaselinePath(from, to) {
|
|
16876
|
+
if (!await exists7(from))
|
|
16877
|
+
return;
|
|
16878
|
+
if (await exists7(to))
|
|
16879
|
+
throw new Error(`skillset: cannot normalize baseline because ${to} already exists`);
|
|
16880
|
+
await mkdir4(dirname9(to), { recursive: true });
|
|
16881
|
+
await rename(from, to);
|
|
16882
|
+
}
|
|
16696
16883
|
async function sourceInventoryFromReleaseState(rootPath, options, fallback) {
|
|
16697
16884
|
const state = await readReleaseState(rootPath, options);
|
|
16698
16885
|
const releaseScopes = Object.entries(state.scopes).filter(([, scope]) => scope.sourceHash !== undefined || scope.removed === true);
|
|
@@ -16875,6 +17062,17 @@ function regionsForRecord(record) {
|
|
|
16875
17062
|
regions.push({ name: "bin", severityBearing: true });
|
|
16876
17063
|
return regions.sort((left, right) => compareStrings(left.name, right.name));
|
|
16877
17064
|
}
|
|
17065
|
+
function mergeRegions(regions) {
|
|
17066
|
+
const byName = new Map;
|
|
17067
|
+
for (const region of regions) {
|
|
17068
|
+
const existing = byName.get(region.name);
|
|
17069
|
+
byName.set(region.name, {
|
|
17070
|
+
name: region.name,
|
|
17071
|
+
severityBearing: region.severityBearing || existing?.severityBearing === true
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
17074
|
+
return [...byName.values()].sort((left, right) => compareStrings(left.name, right.name));
|
|
17075
|
+
}
|
|
16878
17076
|
function companionRegions(path2) {
|
|
16879
17077
|
if (path2 === "hooks")
|
|
16880
17078
|
return [{ name: "hooks", severityBearing: true }];
|
|
@@ -17260,12 +17458,12 @@ async function exists8(path2) {
|
|
|
17260
17458
|
}
|
|
17261
17459
|
|
|
17262
17460
|
// apps/skillset/src/adopt.ts
|
|
17263
|
-
import { mkdtemp as mkdtemp3, mkdir as
|
|
17461
|
+
import { mkdtemp as mkdtemp3, mkdir as mkdir7, readFile as readFile16, rm as rm5, stat as stat14, writeFile as writeFile7 } from "fs/promises";
|
|
17264
17462
|
import { tmpdir as tmpdir2 } from "os";
|
|
17265
17463
|
import { basename as basename7, dirname as dirname12, join as join17, relative as relative15, resolve as resolve7 } from "path";
|
|
17266
17464
|
|
|
17267
17465
|
// apps/skillset/src/import.ts
|
|
17268
|
-
import { mkdir as
|
|
17466
|
+
import { mkdir as mkdir5, mkdtemp as mkdtemp2, readdir as readdir6, readFile as readFile14, realpath, rename as rename2, rm as rm4, stat as stat12, writeFile as writeFile5 } from "fs/promises";
|
|
17269
17467
|
import { homedir } from "os";
|
|
17270
17468
|
import { basename as basename5, dirname as dirname10, join as join15, relative as relative13, resolve as resolve5 } from "path";
|
|
17271
17469
|
|
|
@@ -17273,7 +17471,7 @@ import { basename as basename5, dirname as dirname10, join as join15, relative a
|
|
|
17273
17471
|
import { stat as stat11 } from "fs/promises";
|
|
17274
17472
|
import { join as join14 } from "path";
|
|
17275
17473
|
var ROOT_CONFIG_FILE3 = "config.yaml";
|
|
17276
|
-
var NO_SOURCE_MESSAGE = "skillset: no source plugins, skills,
|
|
17474
|
+
var NO_SOURCE_MESSAGE = "skillset: no source plugins, skills, rules, project agents, or provider source found";
|
|
17277
17475
|
async function seedReleaseBaselines(rootPath, options = {}, seedOptions = {}) {
|
|
17278
17476
|
const sourceDir = options.sourceDir ?? ".skillset";
|
|
17279
17477
|
const configPath = resolveInside(rootPath, join14(sourceDir, ROOT_CONFIG_FILE3));
|
|
@@ -17408,6 +17606,9 @@ async function exists9(path2) {
|
|
|
17408
17606
|
|
|
17409
17607
|
// apps/skillset/src/import.ts
|
|
17410
17608
|
var DEFAULT_SOURCE_DIR2 = ".skillset";
|
|
17609
|
+
var SOURCE_ROOT_DIR3 = "src";
|
|
17610
|
+
var PLUGINS_DIR2 = "plugins";
|
|
17611
|
+
var SKILLS_DIR2 = "skills";
|
|
17411
17612
|
var RECOGNIZED_SOURCE_KEYS = new Set([
|
|
17412
17613
|
"agents",
|
|
17413
17614
|
"allowed_tools",
|
|
@@ -17456,7 +17657,7 @@ async function importSources(options) {
|
|
|
17456
17657
|
files: imports.reduce((total, report) => total + report.files, 0),
|
|
17457
17658
|
imports,
|
|
17458
17659
|
kind: plan.kind,
|
|
17459
|
-
|
|
17660
|
+
renderResults: imports.flatMap((report) => report.renderResults),
|
|
17460
17661
|
...options.provider === undefined ? {} : { provider: options.provider },
|
|
17461
17662
|
sourcePath,
|
|
17462
17663
|
warnings: plan.warnings
|
|
@@ -17466,12 +17667,12 @@ async function importSource(options) {
|
|
|
17466
17667
|
const sourcePath = resolve5(options.sourcePath);
|
|
17467
17668
|
const sourceDir = options.sourceDir ?? DEFAULT_SOURCE_DIR2;
|
|
17468
17669
|
const name = await resolveImportName(sourcePath, options);
|
|
17469
|
-
const targetPath = resolveInside(options.rootPath, join15(sourceDir, options.kind === "plugin" ?
|
|
17670
|
+
const targetPath = resolveInside(options.rootPath, join15(sourceDir, SOURCE_ROOT_DIR3, options.kind === "plugin" ? PLUGINS_DIR2 : SKILLS_DIR2, name));
|
|
17470
17671
|
if (await exists10(targetPath)) {
|
|
17471
17672
|
throw new Error(`skillset: import target already exists: ${targetPath}. ` + "Import never overwrites; remove the existing source or import under a different --name.");
|
|
17472
17673
|
}
|
|
17473
17674
|
const targetParent = dirname10(targetPath);
|
|
17474
|
-
await
|
|
17675
|
+
await mkdir5(targetParent, { recursive: true });
|
|
17475
17676
|
const stagingPath = await mkdtemp2(join15(targetParent, `.${basename5(targetPath)}.tmp-`));
|
|
17476
17677
|
let committed = false;
|
|
17477
17678
|
try {
|
|
@@ -17484,7 +17685,7 @@ async function importSource(options) {
|
|
|
17484
17685
|
if (await exists10(targetPath)) {
|
|
17485
17686
|
throw new Error(`skillset: import target already exists: ${targetPath}. ` + "Import never overwrites; remove the existing source or import under a different --name.");
|
|
17486
17687
|
}
|
|
17487
|
-
await
|
|
17688
|
+
await rename2(stagingPath, targetPath);
|
|
17488
17689
|
committed = true;
|
|
17489
17690
|
let baselineReport;
|
|
17490
17691
|
try {
|
|
@@ -17503,7 +17704,7 @@ async function importSource(options) {
|
|
|
17503
17704
|
files: copiedFiles.length,
|
|
17504
17705
|
inferredSourceFields: classification.recognized,
|
|
17505
17706
|
kind: options.kind,
|
|
17506
|
-
|
|
17707
|
+
renderResults: importRenderResults({
|
|
17507
17708
|
classification,
|
|
17508
17709
|
kind: options.kind,
|
|
17509
17710
|
name,
|
|
@@ -17561,13 +17762,14 @@ function importWarnings(classification) {
|
|
|
17561
17762
|
}
|
|
17562
17763
|
return warnings;
|
|
17563
17764
|
}
|
|
17564
|
-
function
|
|
17765
|
+
function importRenderResults(args) {
|
|
17565
17766
|
const toolPolicyFields = args.classification.targetNative.filter(isClaudeToolPolicyField);
|
|
17566
17767
|
if (toolPolicyFields.length === 0)
|
|
17567
17768
|
return [];
|
|
17568
17769
|
const sourcePath = importSourcePath(args.rootPath, args.targetPath, args.kind);
|
|
17569
17770
|
return [
|
|
17570
|
-
|
|
17771
|
+
defineRenderResult({
|
|
17772
|
+
destination: "skill-frontmatter",
|
|
17571
17773
|
diagnostics: [
|
|
17572
17774
|
{
|
|
17573
17775
|
code: "import-preserved-target-native-frontmatter",
|
|
@@ -17632,8 +17834,8 @@ async function copyImportSource(sourcePath, targetPath, kind, name) {
|
|
|
17632
17834
|
const copied = [];
|
|
17633
17835
|
for (const file of await collectFiles6(copyRoot)) {
|
|
17634
17836
|
const relativePath2 = relativeImportPath(copyRoot, file, kind);
|
|
17635
|
-
await
|
|
17636
|
-
await
|
|
17837
|
+
await mkdir5(dirname10(join15(targetPath, relativePath2)), { recursive: true });
|
|
17838
|
+
await writeFile5(join15(targetPath, relativePath2), await readFile14(file));
|
|
17637
17839
|
copied.push(relativePath2);
|
|
17638
17840
|
}
|
|
17639
17841
|
if (kind === "plugin" && !await exists10(join15(targetPath, "skillset.yaml"))) {
|
|
@@ -17654,11 +17856,11 @@ async function stampImportedOrigins(targetPath, sourcePath, copiedFiles, kind, s
|
|
|
17654
17856
|
}
|
|
17655
17857
|
async function writeYamlSourceOrigin(path2, origin) {
|
|
17656
17858
|
const config2 = parseYamlRecord(await readFile14(path2, "utf8"), path2);
|
|
17657
|
-
await
|
|
17859
|
+
await writeFile5(path2, stringifyYaml(withSkillsetOrigin(config2, origin)));
|
|
17658
17860
|
}
|
|
17659
17861
|
async function writeMarkdownSourceOrigin(path2, origin) {
|
|
17660
17862
|
const parts = parseMarkdown(await readFile14(path2, "utf8"), path2);
|
|
17661
|
-
await
|
|
17863
|
+
await writeFile5(path2, stringifyMarkdown(withSkillsetOrigin(parts.frontmatter, origin), parts.body));
|
|
17662
17864
|
}
|
|
17663
17865
|
function withSkillsetOrigin(record, origin) {
|
|
17664
17866
|
const existing = isJsonRecord(record.skillset) ? record.skillset : {};
|
|
@@ -17699,7 +17901,7 @@ async function resolvePluginConfig(sourcePath) {
|
|
|
17699
17901
|
return;
|
|
17700
17902
|
}
|
|
17701
17903
|
async function collectFiles6(root) {
|
|
17702
|
-
const entries = await
|
|
17904
|
+
const entries = await readdir6(root, { withFileTypes: true });
|
|
17703
17905
|
const files = [];
|
|
17704
17906
|
for (const entry of entries.sort((left, right) => compareStrings(left.name, right.name))) {
|
|
17705
17907
|
const path2 = join15(root, entry.name);
|
|
@@ -17805,7 +18007,7 @@ async function importChildren(sourcePath, kind, predicate) {
|
|
|
17805
18007
|
const stats = await stat12(sourcePath);
|
|
17806
18008
|
if (!stats.isDirectory())
|
|
17807
18009
|
return [];
|
|
17808
|
-
const entries = await
|
|
18010
|
+
const entries = await readdir6(sourcePath, { withFileTypes: true });
|
|
17809
18011
|
const seen = new Set;
|
|
17810
18012
|
const items = [];
|
|
17811
18013
|
for (const entry of entries.sort((left, right) => compareStrings(left.name, right.name))) {
|
|
@@ -17839,7 +18041,7 @@ async function writeImportedPluginConfig(targetPath, name) {
|
|
|
17839
18041
|
license: nativeManifest.license,
|
|
17840
18042
|
keywords: nativeManifest.keywords
|
|
17841
18043
|
};
|
|
17842
|
-
await
|
|
18044
|
+
await writeFile5(join15(targetPath, "skillset.yaml"), stringifyYaml({
|
|
17843
18045
|
skillset: metadata
|
|
17844
18046
|
}));
|
|
17845
18047
|
}
|
|
@@ -17868,7 +18070,7 @@ async function exists10(path2) {
|
|
|
17868
18070
|
}
|
|
17869
18071
|
}
|
|
17870
18072
|
// apps/skillset/src/setup.ts
|
|
17871
|
-
import { mkdir as
|
|
18073
|
+
import { mkdir as mkdir6, readdir as readdir7, readFile as readFile15, realpath as realpath2, stat as stat13, writeFile as writeFile6 } from "fs/promises";
|
|
17872
18074
|
import { basename as basename6, dirname as dirname11, join as join16, relative as relative14, resolve as resolve6 } from "path";
|
|
17873
18075
|
|
|
17874
18076
|
// apps/skillset/src/ci.ts
|
|
@@ -18096,6 +18298,16 @@ function renderCiWorkflow() {
|
|
|
18096
18298
|
var DEFAULT_CREATE_NAME = "my-skillset";
|
|
18097
18299
|
var DEFAULT_GLOBAL_SOURCE = ".skillset/src";
|
|
18098
18300
|
var SETUP_SOURCE_DIR = ".skillset/src";
|
|
18301
|
+
var SETUP_SOURCE_PLACEHOLDERS = [
|
|
18302
|
+
"agents",
|
|
18303
|
+
"hooks",
|
|
18304
|
+
"plugins",
|
|
18305
|
+
"rules",
|
|
18306
|
+
"shared",
|
|
18307
|
+
"skills",
|
|
18308
|
+
"_claude",
|
|
18309
|
+
"_codex"
|
|
18310
|
+
];
|
|
18099
18311
|
async function initSkillset(options = {}) {
|
|
18100
18312
|
const rootPath = await initRootPath(options);
|
|
18101
18313
|
return applySetupPlan("init", rootPath, options);
|
|
@@ -18110,7 +18322,7 @@ async function createSkillset(options = {}) {
|
|
|
18110
18322
|
if (!stats.isDirectory()) {
|
|
18111
18323
|
throw new Error(`skillset: create target exists and is not a directory: ${rootPath}`);
|
|
18112
18324
|
}
|
|
18113
|
-
const entries = await
|
|
18325
|
+
const entries = await readdir7(rootPath);
|
|
18114
18326
|
if (entries.length > 0) {
|
|
18115
18327
|
throw new Error(`skillset: create target must be empty: ${rootPath}`);
|
|
18116
18328
|
}
|
|
@@ -18136,6 +18348,11 @@ async function applySetupPlan(kind, rootPath, options) {
|
|
|
18136
18348
|
files.push({ path: file.path, status: "exists" });
|
|
18137
18349
|
continue;
|
|
18138
18350
|
}
|
|
18351
|
+
if (kind === "init" && file.path === `${SETUP_SOURCE_DIR}/skillset.yaml`) {
|
|
18352
|
+
await validateExistingSourceManifest(absolutePath);
|
|
18353
|
+
files.push({ path: file.path, status: "exists" });
|
|
18354
|
+
continue;
|
|
18355
|
+
}
|
|
18139
18356
|
if (file.path === CI_WORKFLOW_PATH) {
|
|
18140
18357
|
files.push({ path: file.path, status: "exists" });
|
|
18141
18358
|
continue;
|
|
@@ -18150,8 +18367,8 @@ async function applySetupPlan(kind, rootPath, options) {
|
|
|
18150
18367
|
const existing = await readExistingFile(absolutePath);
|
|
18151
18368
|
if (existing !== undefined)
|
|
18152
18369
|
continue;
|
|
18153
|
-
await
|
|
18154
|
-
await
|
|
18370
|
+
await mkdir6(dirname11(absolutePath), { recursive: true });
|
|
18371
|
+
await writeFile6(absolutePath, file.content);
|
|
18155
18372
|
}
|
|
18156
18373
|
if (git?.status === "create")
|
|
18157
18374
|
await initializeGit(rootPath);
|
|
@@ -18197,7 +18414,11 @@ async function gitRoot(cwd) {
|
|
|
18197
18414
|
}
|
|
18198
18415
|
async function validateExistingRootConfig(path2) {
|
|
18199
18416
|
const content = await readFile15(path2, "utf8");
|
|
18200
|
-
|
|
18417
|
+
validateWorkspaceConfigDocument(parseYamlRecord(content, path2), path2);
|
|
18418
|
+
}
|
|
18419
|
+
async function validateExistingSourceManifest(path2) {
|
|
18420
|
+
const content = await readFile15(path2, "utf8");
|
|
18421
|
+
validateRootSourceManifestDocument(parseYamlRecord(content, path2), path2);
|
|
18201
18422
|
}
|
|
18202
18423
|
var GENERATED_INSTRUCTIONS_MARKER = "<!-- Generated by skillset";
|
|
18203
18424
|
var ROOT_INSTRUCTION_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
@@ -18234,7 +18455,7 @@ async function nestedPluginSources(rootPath) {
|
|
|
18234
18455
|
return [];
|
|
18235
18456
|
const realRoot = await realpath2(rootPath);
|
|
18236
18457
|
const sources = [];
|
|
18237
|
-
for (const entry of (await
|
|
18458
|
+
for (const entry of (await readdir7(pluginsPath)).sort()) {
|
|
18238
18459
|
const absolutePath = join16(pluginsPath, entry);
|
|
18239
18460
|
if (!await pathExists(absolutePath))
|
|
18240
18461
|
continue;
|
|
@@ -18279,17 +18500,17 @@ async function detectSurveySkips(rootPath) {
|
|
|
18279
18500
|
relativeTargetPath: "agents",
|
|
18280
18501
|
target: "claude"
|
|
18281
18502
|
}));
|
|
18282
|
-
await maybeSkip(skips, rootPath, ".claude/rules", "rules", "rules are not importable yet; adopt will lower them to .skillset/
|
|
18503
|
+
await maybeSkip(skips, rootPath, ".claude/rules", "rules", "rules are not importable yet; adopt will lower them to .skillset/src/rules/ in the transform milestone", surveySkipOutcome({
|
|
18283
18504
|
featureId: "project-instructions",
|
|
18284
18505
|
path: ".claude/rules",
|
|
18285
|
-
reason: "rules are not importable yet; adopt will lower them to .skillset/
|
|
18506
|
+
reason: "rules are not importable yet; adopt will lower them to .skillset/src/rules/ in the transform milestone",
|
|
18286
18507
|
relativeTargetPath: "rules",
|
|
18287
18508
|
target: "claude"
|
|
18288
18509
|
}));
|
|
18289
18510
|
if (await hasNonSkillCodexContent(rootPath)) {
|
|
18290
18511
|
const reason = "Codex content outside .codex/skills has no portable lowering yet; adopt will lower it to target-native islands in the transform milestone";
|
|
18291
18512
|
skips.push({
|
|
18292
|
-
|
|
18513
|
+
renderResult: surveySkipOutcome({
|
|
18293
18514
|
featureId: "target-native-islands",
|
|
18294
18515
|
path: ".codex",
|
|
18295
18516
|
reason,
|
|
@@ -18304,7 +18525,7 @@ async function detectSurveySkips(rootPath) {
|
|
|
18304
18525
|
for (const path2 of await foreignPluginManifests(rootPath)) {
|
|
18305
18526
|
const reason = "plugin manifest for an unsupported target; skillset can only represent claude and codex surfaces";
|
|
18306
18527
|
skips.push({
|
|
18307
|
-
|
|
18528
|
+
renderResult: foreignManifestSkipOutcome(path2, reason),
|
|
18308
18529
|
path: path2,
|
|
18309
18530
|
reason,
|
|
18310
18531
|
surface: "foreign-manifest"
|
|
@@ -18312,7 +18533,7 @@ async function detectSurveySkips(rootPath) {
|
|
|
18312
18533
|
}
|
|
18313
18534
|
return skips.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
|
|
18314
18535
|
}
|
|
18315
|
-
async function maybeSkip(skips, rootPath, path2, surface, reason,
|
|
18536
|
+
async function maybeSkip(skips, rootPath, path2, surface, reason, renderResult) {
|
|
18316
18537
|
const absolutePath = join16(rootPath, path2);
|
|
18317
18538
|
if (!await pathExists(absolutePath))
|
|
18318
18539
|
return;
|
|
@@ -18320,13 +18541,14 @@ async function maybeSkip(skips, rootPath, path2, surface, reason, loweringOutcom
|
|
|
18320
18541
|
return;
|
|
18321
18542
|
if (await isManagedCandidate(absolutePath))
|
|
18322
18543
|
return;
|
|
18323
|
-
const entries = await
|
|
18544
|
+
const entries = await readdir7(absolutePath);
|
|
18324
18545
|
if (entries.filter((entry) => entry !== ".DS_Store").length === 0)
|
|
18325
18546
|
return;
|
|
18326
|
-
skips.push({ ...
|
|
18547
|
+
skips.push({ ...renderResult === undefined ? {} : { renderResult }, path: path2, reason, surface });
|
|
18327
18548
|
}
|
|
18328
18549
|
function surveySkipOutcome(args) {
|
|
18329
|
-
return
|
|
18550
|
+
return defineRenderResult({
|
|
18551
|
+
destination: "target-native-island",
|
|
18330
18552
|
diagnostics: [
|
|
18331
18553
|
{
|
|
18332
18554
|
code: "adoption-survey-skip",
|
|
@@ -18344,7 +18566,7 @@ function surveySkipOutcome(args) {
|
|
|
18344
18566
|
});
|
|
18345
18567
|
}
|
|
18346
18568
|
function foreignManifestSkipOutcome(path2, reason) {
|
|
18347
|
-
return
|
|
18569
|
+
return defineRenderResult({
|
|
18348
18570
|
diagnostics: [{ code: "adoption-survey-skip", message: reason, path: path2 }],
|
|
18349
18571
|
featureId: "runtime-adapters",
|
|
18350
18572
|
policy: "default",
|
|
@@ -18365,12 +18587,12 @@ async function hasNonSkillCodexContent(rootPath) {
|
|
|
18365
18587
|
return false;
|
|
18366
18588
|
if (await isManagedCandidate(codexPath))
|
|
18367
18589
|
return false;
|
|
18368
|
-
const entries = await
|
|
18590
|
+
const entries = await readdir7(codexPath);
|
|
18369
18591
|
return entries.some((entry) => entry !== "skills" && entry !== ".DS_Store");
|
|
18370
18592
|
}
|
|
18371
18593
|
async function foreignPluginManifests(rootPath) {
|
|
18372
18594
|
const paths = [];
|
|
18373
|
-
for (const entry of (await
|
|
18595
|
+
for (const entry of (await readdir7(rootPath)).sort()) {
|
|
18374
18596
|
if (NATIVE_PLUGIN_MANIFEST_DIRS.has(entry))
|
|
18375
18597
|
continue;
|
|
18376
18598
|
if (!/^\.[a-z][a-z0-9]*-plugin$/.test(entry))
|
|
@@ -18435,7 +18657,7 @@ async function maybeCandidate(candidates, rootPath, path2, kind) {
|
|
|
18435
18657
|
return;
|
|
18436
18658
|
if (await isManagedCandidate(absolutePath))
|
|
18437
18659
|
return;
|
|
18438
|
-
const entries = await
|
|
18660
|
+
const entries = await readdir7(absolutePath);
|
|
18439
18661
|
if (entries.filter((entry) => entry !== ".DS_Store").length === 0)
|
|
18440
18662
|
return;
|
|
18441
18663
|
candidates.push({ kind, path: relative14(rootPath, absolutePath).replaceAll("\\", "/") });
|
|
@@ -18450,12 +18672,20 @@ function setupFiles(options) {
|
|
|
18450
18672
|
const files = [
|
|
18451
18673
|
{
|
|
18452
18674
|
path: ".skillset/config.yaml",
|
|
18453
|
-
content: rootConfig(options.
|
|
18675
|
+
content: rootConfig(options.targets)
|
|
18676
|
+
},
|
|
18677
|
+
{
|
|
18678
|
+
path: `${SETUP_SOURCE_DIR}/skillset.yaml`,
|
|
18679
|
+
content: rootSourceManifest(options.name)
|
|
18454
18680
|
},
|
|
18455
18681
|
{
|
|
18456
18682
|
path: `${SETUP_SOURCE_DIR}/.gitkeep`,
|
|
18457
18683
|
content: ""
|
|
18458
|
-
}
|
|
18684
|
+
},
|
|
18685
|
+
...SETUP_SOURCE_PLACEHOLDERS.map((directory) => ({
|
|
18686
|
+
path: `${SETUP_SOURCE_DIR}/${directory}/.gitkeep`,
|
|
18687
|
+
content: ""
|
|
18688
|
+
}))
|
|
18459
18689
|
];
|
|
18460
18690
|
if (options.kind === "create" && options.global !== true) {
|
|
18461
18691
|
files.unshift({
|
|
@@ -18467,12 +18697,6 @@ function setupFiles(options) {
|
|
|
18467
18697
|
});
|
|
18468
18698
|
}
|
|
18469
18699
|
const include = options.include ?? [];
|
|
18470
|
-
if (include.includes("agents")) {
|
|
18471
|
-
files.push({
|
|
18472
|
-
path: `${SETUP_SOURCE_DIR}/agents/.gitkeep`,
|
|
18473
|
-
content: ""
|
|
18474
|
-
});
|
|
18475
|
-
}
|
|
18476
18700
|
if (include.includes("ci")) {
|
|
18477
18701
|
files.push({ path: CI_WORKFLOW_PATH, content: renderCiWorkflow() });
|
|
18478
18702
|
}
|
|
@@ -18487,7 +18711,7 @@ async function setupGit(kind, rootPath, options) {
|
|
|
18487
18711
|
};
|
|
18488
18712
|
}
|
|
18489
18713
|
async function initializeGit(rootPath) {
|
|
18490
|
-
await
|
|
18714
|
+
await mkdir6(rootPath, { recursive: true });
|
|
18491
18715
|
const proc = Bun.spawn({
|
|
18492
18716
|
cmd: ["git", "init", "-q"],
|
|
18493
18717
|
cwd: rootPath,
|
|
@@ -18505,12 +18729,10 @@ async function initializeGit(rootPath) {
|
|
|
18505
18729
|
${stdout}${stderr}`.trim());
|
|
18506
18730
|
}
|
|
18507
18731
|
}
|
|
18508
|
-
function rootConfig(
|
|
18732
|
+
function rootConfig(targets) {
|
|
18509
18733
|
const targetLines = targets.map((target) => ` - ${target}`).join(`
|
|
18510
18734
|
`);
|
|
18511
18735
|
return [
|
|
18512
|
-
"skillset:",
|
|
18513
|
-
` name: ${name}`,
|
|
18514
18736
|
"compile:",
|
|
18515
18737
|
" targets:",
|
|
18516
18738
|
targetLines,
|
|
@@ -18518,11 +18740,19 @@ function rootConfig(name, targets) {
|
|
|
18518
18740
|
].join(`
|
|
18519
18741
|
`);
|
|
18520
18742
|
}
|
|
18743
|
+
function rootSourceManifest(name) {
|
|
18744
|
+
return [
|
|
18745
|
+
"skillset:",
|
|
18746
|
+
` name: ${name}`,
|
|
18747
|
+
""
|
|
18748
|
+
].join(`
|
|
18749
|
+
`);
|
|
18750
|
+
}
|
|
18521
18751
|
function createReadme(name, targets) {
|
|
18522
18752
|
return [
|
|
18523
18753
|
`# ${name}`,
|
|
18524
18754
|
"",
|
|
18525
|
-
"This repository is a Skillset source repo. Edit files under `.skillset/`, then run Skillset commands to preview or write generated Claude and Codex outputs.",
|
|
18755
|
+
"This repository is a Skillset source repo. Edit files under `.skillset/src/`, then run Skillset commands to preview or write generated Claude and Codex outputs.",
|
|
18526
18756
|
"",
|
|
18527
18757
|
"## Quick Start",
|
|
18528
18758
|
"",
|
|
@@ -18535,10 +18765,11 @@ function createReadme(name, targets) {
|
|
|
18535
18765
|
"",
|
|
18536
18766
|
"## Layout",
|
|
18537
18767
|
"",
|
|
18538
|
-
"- `.skillset/config.yaml` selects compile targets and
|
|
18539
|
-
"- `.skillset/src
|
|
18540
|
-
"- `.skillset/
|
|
18541
|
-
"- `.skillset/
|
|
18768
|
+
"- `.skillset/config.yaml` selects compile targets and destination settings.",
|
|
18769
|
+
"- `.skillset/src/skillset.yaml` names the source loadout and carries root source metadata.",
|
|
18770
|
+
"- `.skillset/src/` is the adaptive project source area for rules, agents, hooks, skills, plugins, shared files, and provider source.",
|
|
18771
|
+
"- `.skillset/src/plugins/` holds plugin source when this repo authors marketplace plugins.",
|
|
18772
|
+
"- `.skillset/src/skills/` holds standalone skill source when this repo authors repo-local or user skill roots.",
|
|
18542
18773
|
"",
|
|
18543
18774
|
`Default compile targets: ${targets.join(", ")}.`,
|
|
18544
18775
|
""
|
|
@@ -18553,7 +18784,8 @@ function createAgentsGuide(name) {
|
|
|
18553
18784
|
"",
|
|
18554
18785
|
"## Working Rules",
|
|
18555
18786
|
"",
|
|
18556
|
-
"- Treat `.skillset/` as editable source.",
|
|
18787
|
+
"- Treat `.skillset/src/` as editable source.",
|
|
18788
|
+
"- Treat `.skillset/config.yaml` as workspace/build configuration.",
|
|
18557
18789
|
"- Treat generated target directories as outputs; do not hand-edit them as source truth.",
|
|
18558
18790
|
"- Run `skillset build --dry-run` before writing generated outputs.",
|
|
18559
18791
|
"- Run `skillset check` before committing source changes.",
|
|
@@ -18620,7 +18852,7 @@ function isErrno2(error, code) {
|
|
|
18620
18852
|
|
|
18621
18853
|
// apps/skillset/src/adopt.ts
|
|
18622
18854
|
var ADOPT_REPORT_DIR = ".skillset/build/adopt";
|
|
18623
|
-
var
|
|
18855
|
+
var INSTRUCTIONS_DIR = ".skillset/src/rules";
|
|
18624
18856
|
async function adoptSkillset(source2, options = {}) {
|
|
18625
18857
|
const { cwd, targets, write, ...buildOptions } = options;
|
|
18626
18858
|
const acquisition = await acquireAdoptSource(source2, cwd ?? process.cwd());
|
|
@@ -18651,7 +18883,7 @@ async function adoptResolvedRoot(acquisition, options = {}) {
|
|
|
18651
18883
|
cutover: [],
|
|
18652
18884
|
imports: [],
|
|
18653
18885
|
lintIssues: [],
|
|
18654
|
-
|
|
18886
|
+
renderResults: surveySkipRenderResults(init.surveySkips),
|
|
18655
18887
|
ok: true,
|
|
18656
18888
|
rootPath: init.rootPath,
|
|
18657
18889
|
setupFiles: init.files,
|
|
@@ -18676,17 +18908,17 @@ async function adoptResolvedRoot(acquisition, options = {}) {
|
|
|
18676
18908
|
buildError = errorMessage3(error);
|
|
18677
18909
|
}
|
|
18678
18910
|
let builtFiles = 0;
|
|
18679
|
-
let
|
|
18680
|
-
...
|
|
18681
|
-
...imports.flatMap((result) => result.
|
|
18911
|
+
let renderResults = [
|
|
18912
|
+
...surveySkipRenderResults(init.surveySkips),
|
|
18913
|
+
...imports.flatMap((result) => result.renderResults)
|
|
18682
18914
|
];
|
|
18683
18915
|
if (buildError === undefined) {
|
|
18684
18916
|
try {
|
|
18685
18917
|
const build2 = await buildSkillsetResult(init.rootPath, { ...buildOptions, isolated: true });
|
|
18686
18918
|
builtFiles = build2.data.length;
|
|
18687
|
-
|
|
18688
|
-
...
|
|
18689
|
-
...build2.
|
|
18919
|
+
renderResults = [
|
|
18920
|
+
...renderResults,
|
|
18921
|
+
...build2.renderResults
|
|
18690
18922
|
];
|
|
18691
18923
|
} catch (error) {
|
|
18692
18924
|
buildError = errorMessage3(error);
|
|
@@ -18703,7 +18935,7 @@ async function adoptResolvedRoot(acquisition, options = {}) {
|
|
|
18703
18935
|
cutover,
|
|
18704
18936
|
imports,
|
|
18705
18937
|
lintIssues,
|
|
18706
|
-
|
|
18938
|
+
renderResults,
|
|
18707
18939
|
ok: imports.every((result) => result.ok) && lintErrors.length === 0 && buildError === undefined,
|
|
18708
18940
|
rootPath: init.rootPath,
|
|
18709
18941
|
setupFiles: init.files,
|
|
@@ -18712,14 +18944,14 @@ async function adoptResolvedRoot(acquisition, options = {}) {
|
|
|
18712
18944
|
write: true
|
|
18713
18945
|
};
|
|
18714
18946
|
const reportDir = join17(init.rootPath, ADOPT_REPORT_DIR);
|
|
18715
|
-
await
|
|
18716
|
-
await
|
|
18717
|
-
await
|
|
18947
|
+
await mkdir7(reportDir, { recursive: true });
|
|
18948
|
+
await writeFile7(join17(reportDir, "report.md"), renderAdoptReportMarkdown(report, { rootPath: init.rootPath }));
|
|
18949
|
+
await writeFile7(join17(reportDir, "report.json"), `${JSON.stringify(report, null, 2)}
|
|
18718
18950
|
`);
|
|
18719
18951
|
return report;
|
|
18720
18952
|
}
|
|
18721
|
-
function
|
|
18722
|
-
return skips.flatMap((skip) => skip.
|
|
18953
|
+
function surveySkipRenderResults(skips) {
|
|
18954
|
+
return skips.flatMap((skip) => skip.renderResult === undefined ? [] : [skip.renderResult]);
|
|
18723
18955
|
}
|
|
18724
18956
|
async function acquireAdoptSource(source2, cwd) {
|
|
18725
18957
|
const localPath = resolve7(cwd, source2);
|
|
@@ -18763,9 +18995,9 @@ async function importCandidate(rootPath, acquisition, candidate, cutover, previe
|
|
|
18763
18995
|
await writeMarkdownSourceOrigin2(join17(rootPath, destination), sourceOriginFor(acquisition, candidate.path));
|
|
18764
18996
|
cutover.push(candidate.path);
|
|
18765
18997
|
previewSources.push(destination);
|
|
18766
|
-
return { candidate, destination, detail: destination,
|
|
18998
|
+
return { candidate, destination, detail: destination, renderResults: [], ok: true, units: [] };
|
|
18767
18999
|
} catch (error) {
|
|
18768
|
-
return { candidate, detail: errorMessage3(error),
|
|
19000
|
+
return { candidate, detail: errorMessage3(error), renderResults: [], ok: false, units: [] };
|
|
18769
19001
|
}
|
|
18770
19002
|
}
|
|
18771
19003
|
try {
|
|
@@ -18793,23 +19025,23 @@ async function importCandidate(rootPath, acquisition, candidate, cutover, previe
|
|
|
18793
19025
|
return {
|
|
18794
19026
|
candidate,
|
|
18795
19027
|
detail: `${units.map((unit) => `${unit.kind} ${unit.name}`).join(", ")} (${batch.files} files)`,
|
|
18796
|
-
|
|
19028
|
+
renderResults: batch.renderResults,
|
|
18797
19029
|
ok: true,
|
|
18798
19030
|
units
|
|
18799
19031
|
};
|
|
18800
19032
|
} catch (error) {
|
|
18801
|
-
return { candidate, detail: errorMessage3(error),
|
|
19033
|
+
return { candidate, detail: errorMessage3(error), renderResults: [], ok: false, units: [] };
|
|
18802
19034
|
}
|
|
18803
19035
|
}
|
|
18804
19036
|
async function importInstructionFile(rootPath, sourceName) {
|
|
18805
|
-
const destinationRelative = `${
|
|
19037
|
+
const destinationRelative = `${INSTRUCTIONS_DIR}/${sourceName.toLowerCase()}`;
|
|
18806
19038
|
const destination = join17(rootPath, destinationRelative);
|
|
18807
19039
|
if (await exists11(destination)) {
|
|
18808
19040
|
throw new Error(`skillset: instructions import target already exists: ${destinationRelative}. ` + "Adopt never overwrites; remove the existing file or merge by hand.");
|
|
18809
19041
|
}
|
|
18810
19042
|
const content = await readFile16(join17(rootPath, sourceName));
|
|
18811
|
-
await
|
|
18812
|
-
await
|
|
19043
|
+
await mkdir7(dirname12(destination), { recursive: true });
|
|
19044
|
+
await writeFile7(destination, content);
|
|
18813
19045
|
return destinationRelative;
|
|
18814
19046
|
}
|
|
18815
19047
|
function sourceOriginFor(acquisition, path2) {
|
|
@@ -18822,7 +19054,7 @@ function relativeOriginPath(rootPath, sourcePath, copiedFile) {
|
|
|
18822
19054
|
}
|
|
18823
19055
|
async function writeMarkdownSourceOrigin2(path2, origin) {
|
|
18824
19056
|
const parts = parseMarkdown(await readFile16(path2, "utf8"), path2);
|
|
18825
|
-
await
|
|
19057
|
+
await writeFile7(path2, stringifyMarkdown(withSkillsetOrigin2(parts.frontmatter, origin), parts.body));
|
|
18826
19058
|
}
|
|
18827
19059
|
function withSkillsetOrigin2(record, origin) {
|
|
18828
19060
|
const existing = isJsonRecord(record.skillset) ? record.skillset : {};
|
|
@@ -18882,7 +19114,7 @@ dialect: claude
|
|
|
18882
19114
|
---
|
|
18883
19115
|
|
|
18884
19116
|
${raw}`;
|
|
18885
|
-
await
|
|
19117
|
+
await writeFile7(path2, updated);
|
|
18886
19118
|
return true;
|
|
18887
19119
|
}
|
|
18888
19120
|
function markdownBody(raw, label) {
|
|
@@ -18904,7 +19136,7 @@ function renderAdoptReportMarkdown(report, opts) {
|
|
|
18904
19136
|
if (report.alreadyAdopted) {
|
|
18905
19137
|
lines.push("- note: the repo already had `.skillset/config.yaml`; adoption proceeded against the existing source tree");
|
|
18906
19138
|
}
|
|
18907
|
-
lines.push(`- imports: ${succeeded.length} succeeded, ${failed.length} failed`, `- lint: ${lintErrors.length} error(s), ${lintWarnings.length} warning(s)`, report.buildError === undefined ? `- build (isolated): ${report.builtFiles} generated files` : "- build (isolated): failed", `-
|
|
19139
|
+
lines.push(`- imports: ${succeeded.length} succeeded, ${failed.length} failed`, `- lint: ${lintErrors.length} error(s), ${lintWarnings.length} warning(s)`, report.buildError === undefined ? `- build (isolated): ${report.builtFiles} generated files` : "- build (isolated): failed", `- render results: ${report.renderResults.length}`, "");
|
|
18908
19140
|
lines.push("## Acquisition", "");
|
|
18909
19141
|
if (report.acquisition.kind === "git") {
|
|
18910
19142
|
lines.push("- source: git remote", `- repo: \`${report.acquisition.repo}\``, `- ref: \`${report.acquisition.ref}\``, `- clone: \`${report.acquisition.rootPath}\``, "");
|
|
@@ -18993,15 +19225,15 @@ function renderAdoptReportMarkdown(report, opts) {
|
|
|
18993
19225
|
} else {
|
|
18994
19226
|
lines.push("```", report.buildError.trimEnd(), "```", "");
|
|
18995
19227
|
}
|
|
18996
|
-
lines.push("###
|
|
18997
|
-
if (report.
|
|
18998
|
-
lines.push("No
|
|
19228
|
+
lines.push("### Render results", "");
|
|
19229
|
+
if (report.renderResults.length === 0) {
|
|
19230
|
+
lines.push("No render results recorded.", "");
|
|
18999
19231
|
} else {
|
|
19000
|
-
for (const summary of
|
|
19232
|
+
for (const summary of summarizeRenderResults(report.renderResults)) {
|
|
19001
19233
|
lines.push(`- ${summary}`);
|
|
19002
19234
|
}
|
|
19003
19235
|
lines.push("");
|
|
19004
|
-
lines.push("Full structured
|
|
19236
|
+
lines.push("Full structured render results are in `report.json` and in the isolated `.skillset.lock` files when the isolated build completes.", "");
|
|
19005
19237
|
}
|
|
19006
19238
|
lines.push("## Cutover", "");
|
|
19007
19239
|
lines.push(`1. Review the generated mirror under \`${ISOLATED_OUT_ROOT}/\` against the originals.`);
|
|
@@ -19019,7 +19251,7 @@ function renderAdoptReportMarkdown(report, opts) {
|
|
|
19019
19251
|
`).trimEnd()}
|
|
19020
19252
|
`;
|
|
19021
19253
|
}
|
|
19022
|
-
function
|
|
19254
|
+
function summarizeRenderResults(outcomes) {
|
|
19023
19255
|
const counts = new Map;
|
|
19024
19256
|
for (const outcome of outcomes) {
|
|
19025
19257
|
const key = `${outcome.target ?? "workspace"} ${outcome.status}`;
|
|
@@ -19059,7 +19291,7 @@ async function exists11(path2) {
|
|
|
19059
19291
|
|
|
19060
19292
|
// apps/skillset/src/change-workflow.ts
|
|
19061
19293
|
import { createHash as createHash6, randomBytes } from "crypto";
|
|
19062
|
-
import { mkdir as
|
|
19294
|
+
import { mkdir as mkdir8, readFile as readFile17, stat as stat15, writeFile as writeFile8 } from "fs/promises";
|
|
19063
19295
|
import { isAbsolute as isAbsolute2, join as join18, resolve as resolve8 } from "path";
|
|
19064
19296
|
var PENDING_DIR2 = "changes/pending";
|
|
19065
19297
|
var HISTORY_FILE2 = "changes/history.jsonl";
|
|
@@ -19093,8 +19325,8 @@ async function addChangeEntry(rootPath, options) {
|
|
|
19093
19325
|
scopes,
|
|
19094
19326
|
sourceHashes
|
|
19095
19327
|
});
|
|
19096
|
-
await
|
|
19097
|
-
await
|
|
19328
|
+
await mkdir8(resolveInside(rootPath, join18(sourceDir, PENDING_DIR2)), { recursive: true });
|
|
19329
|
+
await writeFile8(absolutePath, stringifyMarkdown(entryFrontmatter, reason), "utf8");
|
|
19098
19330
|
const [entry] = await readPendingChangeEntries(rootPath, statusOptions).then((entries) => entries.filter((item) => item.id === id));
|
|
19099
19331
|
if (entry === undefined)
|
|
19100
19332
|
throw new Error(`skillset: failed to read created change entry ${id}`);
|
|
@@ -19110,7 +19342,7 @@ async function updateChangeReason(rootPath, options) {
|
|
|
19110
19342
|
const body = options.append ? `${parts.body.trimEnd()}
|
|
19111
19343
|
|
|
19112
19344
|
${newReason}` : newReason;
|
|
19113
|
-
await
|
|
19345
|
+
await writeFile8(absolutePath, stringifyMarkdown(parts.frontmatter, body), "utf8");
|
|
19114
19346
|
const updated = resolvePendingChangeRef(await readPendingChangeEntries(rootPath, options), entry.id ?? options.ref);
|
|
19115
19347
|
const refs = refIndex([updated], await readHistoryEntries(rootPath, options));
|
|
19116
19348
|
return { entry: pendingView(updated, refs) };
|
|
@@ -19846,10 +20078,10 @@ function renderAgentRuntimeSnippet(target) {
|
|
|
19846
20078
|
// apps/skillset/src/runtime-hooks/source-gate.ts
|
|
19847
20079
|
var HOOK_RELEVANT_SOURCE_PATHS = [
|
|
19848
20080
|
".skillset/config.yaml",
|
|
19849
|
-
".skillset/
|
|
19850
|
-
".skillset/skills",
|
|
19851
|
-
".skillset/plugins",
|
|
19852
|
-
".skillset/shared",
|
|
20081
|
+
".skillset/src/rules",
|
|
20082
|
+
".skillset/src/skills",
|
|
20083
|
+
".skillset/src/plugins",
|
|
20084
|
+
".skillset/src/shared",
|
|
19853
20085
|
".skillset/src",
|
|
19854
20086
|
".skillset/changes/pending"
|
|
19855
20087
|
];
|
|
@@ -19936,7 +20168,7 @@ function result(args) {
|
|
|
19936
20168
|
};
|
|
19937
20169
|
}
|
|
19938
20170
|
// apps/skillset/src/release.ts
|
|
19939
|
-
import { appendFile, mkdir as
|
|
20171
|
+
import { appendFile, mkdir as mkdir9, readFile as readFile19, rm as rm6, stat as stat17, writeFile as writeFile9 } from "fs/promises";
|
|
19940
20172
|
import { createHash as createHash7 } from "crypto";
|
|
19941
20173
|
import { dirname as dirname13, join as join20 } from "path";
|
|
19942
20174
|
var HISTORY_FILE3 = "changes/history.jsonl";
|
|
@@ -20142,7 +20374,7 @@ async function appendHistory(rootPath, sourceDir, entries, appliedAt, files) {
|
|
|
20142
20374
|
return;
|
|
20143
20375
|
const relativePath2 = join20(sourceDir, HISTORY_FILE3).replaceAll("\\", "/");
|
|
20144
20376
|
const absolutePath = resolveInside(rootPath, relativePath2);
|
|
20145
|
-
await
|
|
20377
|
+
await mkdir9(dirname13(absolutePath), { recursive: true });
|
|
20146
20378
|
const lines = entries.flatMap((entry) => entry.id === undefined || entry.bump === undefined ? [] : [
|
|
20147
20379
|
JSON.stringify({
|
|
20148
20380
|
appliedAt,
|
|
@@ -20167,7 +20399,7 @@ async function appendReleaseRecord(rootPath, sourceDir, plan, appliedAt, files)
|
|
|
20167
20399
|
return;
|
|
20168
20400
|
const relativePath2 = join20(sourceDir, RELEASES_FILE).replaceAll("\\", "/");
|
|
20169
20401
|
const absolutePath = resolveInside(rootPath, relativePath2);
|
|
20170
|
-
await
|
|
20402
|
+
await mkdir9(dirname13(absolutePath), { recursive: true });
|
|
20171
20403
|
await appendFile(absolutePath, `${JSON.stringify({
|
|
20172
20404
|
appliedAt,
|
|
20173
20405
|
baseline: { hashSchema: SOURCE_HASH_SCHEMA, kind: "source-hashes" },
|
|
@@ -20211,8 +20443,8 @@ async function restoreSnapshots(rootPath, snapshots) {
|
|
|
20211
20443
|
await rm6(absolutePath, { force: true });
|
|
20212
20444
|
continue;
|
|
20213
20445
|
}
|
|
20214
|
-
await
|
|
20215
|
-
await
|
|
20446
|
+
await mkdir9(dirname13(absolutePath), { recursive: true });
|
|
20447
|
+
await writeFile9(absolutePath, snapshot.content);
|
|
20216
20448
|
}
|
|
20217
20449
|
}
|
|
20218
20450
|
async function exists14(path2) {
|
|
@@ -20256,7 +20488,7 @@ function releaseIdFor(scopes) {
|
|
|
20256
20488
|
return hash.digest("hex").slice(0, 12);
|
|
20257
20489
|
}
|
|
20258
20490
|
// apps/skillset/src/test-runner.ts
|
|
20259
|
-
import { cp, mkdir as
|
|
20491
|
+
import { cp, mkdir as mkdir10, mkdtemp as mkdtemp4, readFile as readFile20, rm as rm7, stat as stat18, writeFile as writeFile10 } from "fs/promises";
|
|
20260
20492
|
import { createHash as createHash8, randomBytes as randomBytes2 } from "crypto";
|
|
20261
20493
|
import { dirname as dirname14, join as join21, relative as relative16, resolve as resolve9 } from "path";
|
|
20262
20494
|
import { tmpdir as tmpdir3 } from "os";
|
|
@@ -20287,7 +20519,7 @@ async function runSkillsetTest(rootPath, name, options = {}) {
|
|
|
20287
20519
|
const workspaceLockPath = resolveInside(rootPath, ".skillset.lock");
|
|
20288
20520
|
const ignoredSourceBuildPath = resolveInside(rootPath, join21(sourceDir, "build"));
|
|
20289
20521
|
try {
|
|
20290
|
-
await
|
|
20522
|
+
await mkdir10(stagingWorkspacePath, { recursive: true });
|
|
20291
20523
|
await cp(sourcePath, stagingSourcePath, {
|
|
20292
20524
|
filter: (path2) => !isSameOrInside2(ignoredSourceBuildPath, path2),
|
|
20293
20525
|
recursive: true
|
|
@@ -20312,7 +20544,7 @@ async function runSkillsetTest(rootPath, name, options = {}) {
|
|
|
20312
20544
|
if (assertions.every((assertion) => assertion.ok)) {
|
|
20313
20545
|
await validateActivationExpectations(stagingWorkspacePath, declaration, buildOptions);
|
|
20314
20546
|
}
|
|
20315
|
-
await
|
|
20547
|
+
await mkdir10(runPath, { recursive: true });
|
|
20316
20548
|
await cp(stagingWorkspacePath, workspacePath, { recursive: true });
|
|
20317
20549
|
const activationPath = await writeActivationProbes(runPath, declaration);
|
|
20318
20550
|
const ok = assertions.every((assertion) => assertion.ok);
|
|
@@ -20337,8 +20569,8 @@ async function runSkillsetTest(rootPath, name, options = {}) {
|
|
|
20337
20569
|
...activationReport,
|
|
20338
20570
|
workspacePath: relative16(rootPath, workspacePath)
|
|
20339
20571
|
};
|
|
20340
|
-
await
|
|
20341
|
-
await
|
|
20572
|
+
await writeFile10(reportPath, renderValidatedJson(report, relative16(rootPath, reportPath)), "utf8");
|
|
20573
|
+
await writeFile10(reportMarkdownPath, renderMarkdownReport(report), "utf8");
|
|
20342
20574
|
await refreshLatest(buildRoot, runPath, latestPath, report, rootPath);
|
|
20343
20575
|
return {
|
|
20344
20576
|
assertions,
|
|
@@ -20603,16 +20835,16 @@ async function writeActivationProbes(runPath, declaration) {
|
|
|
20603
20835
|
if (probes.length === 0)
|
|
20604
20836
|
continue;
|
|
20605
20837
|
const targetRoot = join21(activationRoot, target);
|
|
20606
|
-
await
|
|
20838
|
+
await mkdir10(targetRoot, { recursive: true });
|
|
20607
20839
|
const records = probes.map((probe) => activationProbeRecord(probe, target));
|
|
20608
|
-
await
|
|
20840
|
+
await writeFile10(join21(targetRoot, "probes.json"), renderValidatedJson({
|
|
20609
20841
|
probes: records,
|
|
20610
20842
|
schemaVersion: TEST_SCHEMA,
|
|
20611
20843
|
target
|
|
20612
20844
|
}, `activation ${target} probes`), "utf8");
|
|
20613
20845
|
for (const record of records) {
|
|
20614
20846
|
const name = typeof record.name === "string" ? record.name : "probe";
|
|
20615
|
-
await
|
|
20847
|
+
await writeFile10(join21(targetRoot, `${name}.md`), renderActivationProbeMarkdown(record), "utf8");
|
|
20616
20848
|
}
|
|
20617
20849
|
}
|
|
20618
20850
|
return activationRoot;
|
|
@@ -20676,7 +20908,7 @@ async function refreshLatest(buildRoot, runPath, latestPath, report, rootPath) {
|
|
|
20676
20908
|
source: report.source,
|
|
20677
20909
|
workspacePath: relative16(rootPath, join21(latestPath, "workspace"))
|
|
20678
20910
|
};
|
|
20679
|
-
await
|
|
20911
|
+
await writeFile10(join21(buildRoot, "latest.json"), renderValidatedJson(latest, relative16(rootPath, join21(buildRoot, "latest.json"))), "utf8");
|
|
20680
20912
|
}
|
|
20681
20913
|
function renderMarkdownReport(report) {
|
|
20682
20914
|
const assertions = Array.isArray(report.assertions) ? report.assertions : [];
|
|
@@ -20722,7 +20954,7 @@ async function pathExists2(path2) {
|
|
|
20722
20954
|
async function copyIfExists(sourcePath, targetPath) {
|
|
20723
20955
|
if (!await pathExists2(sourcePath))
|
|
20724
20956
|
return;
|
|
20725
|
-
await
|
|
20957
|
+
await mkdir10(dirname14(targetPath), { recursive: true });
|
|
20726
20958
|
await cp(sourcePath, targetPath);
|
|
20727
20959
|
}
|
|
20728
20960
|
async function copyWorkspaceManagedFiles(rootPath, stagingWorkspacePath, workspaceLockPath, sourceDir) {
|
|
@@ -20788,8 +21020,8 @@ var USAGE = [
|
|
|
20788
21020
|
" skillset hooks print --target <claude|codex> --agent-runtime",
|
|
20789
21021
|
" skillset hooks run <post-tool-use|stop> [--root <path>]",
|
|
20790
21022
|
" skillset adopt <path> [--yes|--dry-run] [--targets claude,codex] [--root <path>]",
|
|
20791
|
-
" skillset init [path] [--yes|--dry-run] [--targets claude,codex] [--include
|
|
20792
|
-
" skillset create [path|--global] [--yes|--dry-run] [--targets claude,codex] [--include
|
|
21023
|
+
" skillset init [path] [--yes|--dry-run] [--targets claude,codex] [--include ci] [--name <name>] [--root <path>]",
|
|
21024
|
+
" skillset create [path|--global] [--yes|--dry-run] [--targets claude,codex] [--include ci] [--name <name>] [--root <path>]",
|
|
20793
21025
|
" skillset explain <path> [--json] [--scope <scope>] [--root <path>] [--source <dir>]",
|
|
20794
21026
|
" skillset import <path> [--kind <skill|skills|plugin|plugins>] [--from <provider>] [--name <name>] [--root <path>] [--source <dir>]",
|
|
20795
21027
|
" skillset import <claude|codex|agents> [--root <path>] [--source <dir>]"
|
|
@@ -20868,8 +21100,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
20868
21100
|
});
|
|
20869
21101
|
if (ciReportPath !== undefined) {
|
|
20870
21102
|
const reportPath = resolve10(ciReportPath);
|
|
20871
|
-
await
|
|
20872
|
-
await
|
|
21103
|
+
await mkdir11(dirname15(reportPath), { recursive: true });
|
|
21104
|
+
await writeFile11(reportPath, renderCiReportMarkdown(report));
|
|
20873
21105
|
}
|
|
20874
21106
|
printCiReport(report);
|
|
20875
21107
|
if (!report.ok)
|
|
@@ -21182,8 +21414,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21182
21414
|
console.log(` claude: ${feature2.targetSupport.claude.status}`);
|
|
21183
21415
|
console.log(` codex: ${feature2.targetSupport.codex.status}`);
|
|
21184
21416
|
}
|
|
21185
|
-
for (const outcome of result3.
|
|
21186
|
-
|
|
21417
|
+
for (const outcome of result3.renderResults) {
|
|
21418
|
+
printRenderResult(outcome);
|
|
21187
21419
|
}
|
|
21188
21420
|
for (const note of result3.notes)
|
|
21189
21421
|
console.log(` note: ${note}`);
|
|
@@ -21214,14 +21446,14 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21214
21446
|
console.log(` features: ${report.featureCapabilities.total} registry entries; status ${formatCountSummary(report.featureCapabilities.byFeatureStatus)}`);
|
|
21215
21447
|
console.log(` feature support: claude ${formatCountSummary(report.featureCapabilities.byTargetSupport.claude)}`);
|
|
21216
21448
|
console.log(` feature support: codex ${formatCountSummary(report.featureCapabilities.byTargetSupport.codex)}`);
|
|
21217
|
-
for (const outcome of report.
|
|
21218
|
-
|
|
21449
|
+
for (const outcome of report.notableRenderResults) {
|
|
21450
|
+
printRenderResult(outcome);
|
|
21219
21451
|
}
|
|
21220
21452
|
if (report.ok) {
|
|
21221
|
-
if (report.
|
|
21453
|
+
if (report.notableRenderResults.length === 0) {
|
|
21222
21454
|
console.log("skillset: doctor found no problems");
|
|
21223
21455
|
} else {
|
|
21224
|
-
console.log(`skillset: doctor found ${report.
|
|
21456
|
+
console.log(`skillset: doctor found ${report.notableRenderResults.length} render result advisor${report.notableRenderResults.length === 1 ? "y" : "ies"}`);
|
|
21225
21457
|
}
|
|
21226
21458
|
} else {
|
|
21227
21459
|
const problems = [];
|
|
@@ -21231,8 +21463,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21231
21463
|
problems.push("generated-output drift");
|
|
21232
21464
|
if (report.buildError !== undefined)
|
|
21233
21465
|
problems.push("a build error");
|
|
21234
|
-
if (report.
|
|
21235
|
-
problems.push(`${report.
|
|
21466
|
+
if (report.notableRenderResults.length > 0) {
|
|
21467
|
+
problems.push(`${report.notableRenderResults.length} render result advisor${report.notableRenderResults.length === 1 ? "y" : "ies"}`);
|
|
21236
21468
|
}
|
|
21237
21469
|
console.log(`skillset: doctor found ${problems.join(" and ")}`);
|
|
21238
21470
|
process.exitCode = 1;
|
|
@@ -21598,11 +21830,12 @@ function formatFeatureSupport(support) {
|
|
|
21598
21830
|
function formatCountSummary(counts) {
|
|
21599
21831
|
return Object.entries(counts).sort(([left], [right]) => left.localeCompare(right)).map(([key, count]) => `${key} ${count}`).join(", ");
|
|
21600
21832
|
}
|
|
21601
|
-
function
|
|
21833
|
+
function printRenderResult(outcome) {
|
|
21602
21834
|
const target = outcome.target ?? "workspace";
|
|
21835
|
+
const destination = outcome.destination === undefined ? "" : ` -> ${outcome.destination}`;
|
|
21603
21836
|
const policy = outcome.policy === undefined ? "" : ` policy: ${outcome.policy}`;
|
|
21604
21837
|
const reason = outcome.reason === undefined ? "" : ` reason: ${outcome.reason}`;
|
|
21605
|
-
console.log(`
|
|
21838
|
+
console.log(` render [${target}] ${outcome.sourceUnit}: ${outcome.featureId}${destination} ${outcome.status}${policy}${reason}`);
|
|
21606
21839
|
if (outcome.outputs !== undefined && outcome.outputs.length > 0) {
|
|
21607
21840
|
console.log(` outputs: ${outcome.outputs.map((output) => output.path).join(", ")}`);
|
|
21608
21841
|
}
|
|
@@ -22122,8 +22355,8 @@ function mergeSetupIncludes(current, value) {
|
|
|
22122
22355
|
throw new Error("skillset: --include requires at least one value");
|
|
22123
22356
|
const seen = new Set(current ?? []);
|
|
22124
22357
|
for (const include of includes) {
|
|
22125
|
-
if (include !== "
|
|
22126
|
-
throw new Error("skillset: expected --include
|
|
22358
|
+
if (include !== "ci") {
|
|
22359
|
+
throw new Error("skillset: expected --include ci");
|
|
22127
22360
|
}
|
|
22128
22361
|
seen.add(include);
|
|
22129
22362
|
}
|