skillset 0.13.3 → 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.
Files changed (3) hide show
  1. package/dist/cli.js +595 -336
  2. package/dist/create.js +595 -336
  3. 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 mkdir10, writeFile as writeFile10 } from "fs/promises";
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
- loweringOwner: "apps/skillset/src/test-runner.ts",
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
- loweringOwner: "apps/skillset/src/change-entries.ts",
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 lowering tests")],
7121
+ evidence: [test("apps/skillset/src/__tests__/contract.test.ts", "SET-40 dependency rendering tests")],
7122
7122
  id: "dependencies",
7123
7123
  kind: "metadata",
7124
- loweringOwner: "packages/core/src/dependencies.ts",
7124
+ renderOwner: "packages/core/src/dependencies.ts",
7125
7125
  sourceShape: "plugin skillset.yaml dependencies",
7126
7126
  status: "implemented",
7127
- summary: "Declares plugin dependencies and lowers target-specific install/awareness behavior.",
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
- loweringOwner: "packages/core/src/distribution.ts",
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
- loweringOwner: "packages/core/src/feature-registry.ts",
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, lowering owners, and validation owners.",
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/lowering-outcomes.md"],
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/lowering-outcome.ts"),
7180
- source("packages/core/src/lowering-outcome-collector.ts"),
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__/lowering-outcome.test.ts", "lowering outcome schema validation coverage"),
7184
- test("packages/core/src/__tests__/lowering-outcome-build.test.ts", "build lowering outcomes cover emitted, target-native, transformed, unsupported, policy-gated, scoped, and status-matrix outcomes"),
7185
- test("apps/skillset/src/__tests__/contract.test.ts", "SET-86 import and build warnings carry lowering outcome codes"),
7186
- test("apps/skillset/src/__tests__/adopt.test.ts", "SET-86 adopt survey skips carry lowering outcome codes")
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: "lowering-outcomes",
7188
+ id: "render-results",
7189
7189
  kind: "workflow",
7190
- loweringOwner: "packages/core/src/lowering-outcome-collector.ts",
7191
- sourceShape: "rendered build graph, generated lock items, companion files, unsupported feature records, and lowering-relevant import/adopt report warnings",
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 lowering facts for emitted, transformed, degraded, skipped, unsupported, and externally managed source units.",
7193
+ summary: "Records per-build render facts for rendered, transformed, degraded, skipped, unsupported, and externally managed source units.",
7194
7194
  targetSupport: notTargetRuntime(),
7195
- title: "Lowering Outcomes",
7196
- validationOwner: "packages/core/src/lowering-outcome.ts"
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
- loweringOwner: "packages/core/src/output-safety.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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 lowering coverage")],
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
- loweringOwner: "packages/core/src/render.ts",
7448
- sourceShape: ".skillset/instructions/**/*.md",
7447
+ renderOwner: "packages/core/src/render.ts",
7448
+ sourceShape: ".skillset/src/rules/**/*.md",
7449
7449
  status: "implemented",
7450
- summary: "Lowers project instructions to Claude rules and directory-local Codex AGENTS.md files.",
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
- loweringOwner: "packages/core/src/render.ts",
7460
+ renderOwner: "packages/core/src/render.ts",
7461
7461
  sourceShape: ".skillset/src/agents/*.md",
7462
7462
  status: "implemented",
7463
- summary: "Lowers portable project agents to Claude Markdown agents and Codex TOML agents.",
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
- loweringOwner: "packages/core/src/feature-registry.ts",
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
- loweringOwner: "apps/skillset/src/release.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "apps/skillset/src/change-status.ts",
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
- loweringOwner: "packages/core/src/render.ts",
7605
- sourceShape: ".skillset/src/<target>/** and plugin-local target-native subdirs",
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 lowering coverage")],
7614
+ evidence: [test("apps/skillset/src/__tests__/skillset.test.ts", "tool policy rendering coverage")],
7615
7615
  id: "tool-intent",
7616
7616
  kind: "source",
7617
- loweringOwner: "packages/core/src/render.ts",
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
- loweringOwner: "future",
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
- loweringOwner: "packages/core/src/version-audit.ts",
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
- loweringOwner: "apps/skillset/src/cli-core.ts",
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 lowering them into target runtime artifacts.",
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
- loweringOwner: "packages/core/src/render.ts",
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/lowering-outcome.ts
7800
- var LOWERING_OUTCOME_SCHEMA = "skillset-lowering-outcome@1";
7801
- var LOWERING_OUTCOME_STATUS_VALUES = [
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 SkillsetLoweringError extends Error {
7815
- loweringOutcomes;
7816
- constructor(message, loweringOutcomes) {
7814
+ class SkillsetRenderResultError extends Error {
7815
+ renderResults;
7816
+ constructor(message, renderResults) {
7817
7817
  super(message);
7818
- this.name = "SkillsetLoweringError";
7819
- this.loweringOutcomes = loweringOutcomes.map(normalizeLoweringOutcome);
7818
+ this.name = "SkillsetRenderResultError";
7819
+ this.renderResults = renderResults.map(normalizeRenderResult);
7820
7820
  }
7821
7821
  }
7822
- function defineLoweringOutcome(input) {
7823
- const outcome = normalizeLoweringOutcome({
7822
+ function defineRenderResult(input) {
7823
+ const outcome = normalizeRenderResult({
7824
7824
  ...input,
7825
- schema: input.schema ?? LOWERING_OUTCOME_SCHEMA
7825
+ schema: input.schema ?? RENDER_RESULT_SCHEMA
7826
7826
  });
7827
- assertLoweringOutcome(outcome);
7827
+ assertRenderResult(outcome);
7828
7828
  return outcome;
7829
7829
  }
7830
- function normalizeLoweringOutcome(outcome) {
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 assertLoweringOutcome(outcome) {
7846
- if (outcome.schema !== LOWERING_OUTCOME_SCHEMA) {
7847
- throw new Error(`skillset: unsupported lowering outcome schema ${outcome.schema}`);
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: lowering outcome sourceUnit is required");
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: lowering outcome featureId is required");
7854
+ throw new Error("skillset: render result featureId is required");
7854
7855
  }
7855
- if (!new Set(LOWERING_OUTCOME_STATUS_VALUES).has(outcome.status)) {
7856
- throw new Error(`skillset: unknown lowering outcome status ${outcome.status}`);
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: lowering outcome ${outcome.status} status requires a reason`);
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: lowering outcome output path is required");
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: lowering outcome diagnostic code is required");
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: lowering outcome evidence ref is required");
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: lowering outcome external docs evidence requires verifiedAt");
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/lowering-outcome-collector.ts
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 COMPILE_UNSUPPORTED_POLICIES = new Set([
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
- unsupported: "error"
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 !== "unsupported") {
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 unsupported = readCompileUnsupportedPolicy(compile, `${label}.compile.unsupported`);
8054
- if (unsupported !== "error") {
8055
- throw new Error(`skillset: ${label}.compile.unsupported ${unsupported} is reserved but not supported yet; ` + "use error until warning, skip, or force provenance is implemented");
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
- unsupported
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 readCompileUnsupportedPolicy(record, label) {
8337
- const value = record.unsupported;
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 (!COMPILE_UNSUPPORTED_POLICIES.has(value)) {
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/lowering-outcome-collector.ts
9112
+ // packages/core/src/render-result-collector.ts
9091
9113
  var LOCK_FILE = ".skillset.lock";
9092
9114
  var TARGETS2 = ["claude", "codex"];
9093
- function collectLoweringOutcomes(graph, rendered, options) {
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 lowering outcomes`);
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 lowering outcomes`);
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 defineLoweringOutcome({
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 defineLoweringOutcome({
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" : "emitted",
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 defineLoweringOutcome({
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(defineLoweringOutcome({
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(defineLoweringOutcome({
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 "emitted";
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/lowering-policy.ts
9591
- function enforceLoweringOutcomePolicy(loweringOutcomes, unsupportedPolicy) {
9592
- const blocked = loweringOutcomes.filter(isPolicyBlockingOutcome);
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 SkillsetLoweringError(formatLoweringPolicyError(blocked, unsupportedPolicy), blocked);
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 formatLoweringPolicyError(outcomes, unsupportedPolicy) {
9601
- const noun = outcomes.length === 1 ? "outcome" : "outcomes";
9647
+ function formatRenderResultPolicyError(outcomes, unsupportedPolicy) {
9648
+ const noun = outcomes.length === 1 ? "render result" : "render results";
9602
9649
  return [
9603
- `skillset: lowering policy blocked ${outcomes.length} ${noun} (compile.unsupported: ${unsupportedPolicy})`,
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 INSTRUCTIONS_DIR = "instructions";
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
- validateConfigDocument(rootConfig, rootConfigPath, { allowCompile: true });
13223
- const metadata = readSkillsetMetadata(rootConfig, rootConfigPath);
13224
- validateSchemaField(metadata, `${rootConfigPath}.skillset.schema`);
13225
- validateVersionField(metadata, `${rootConfigPath}.skillset.version`);
13226
- readSkillsetName(metadata, basename2(rootPath), rootConfigPath);
13227
- const outputs = readOutputConfig(rootConfig, metadata, options.distDir === undefined ? {} : { distDir: options.distDir });
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 validateSupports(rootConfig.supports, { label: rootConfigPath, rootPath, warnings });
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, instructions, project agents, or target-native islands found under ${sourceDir}/`);
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, TARGET_NATIVE_SOURCE_DIR));
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, "claude"), "claude"));
13316
- islands.push(...await loadTargetIsland(rootPath, join8(srcPath, "codex"), "codex"));
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, "claude"), "claude", plugin.id));
13323
- islands.push(...await loadTargetIsland(rootPath, join8(pluginPath, "codex"), "codex", plugin.id));
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/codex/rules/; ` + "Codex .rules are project-only command policy",
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, TARGET_NATIVE_SOURCE_DIR, PROJECT_AGENTS_DIR));
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, INSTRUCTIONS_DIR));
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: INSTRUCTIONS_DIR };
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: INSTRUCTIONS_DIR
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, "shared"))
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 loweringOutcomes = collectLoweringOutcomes(graph, allRendered, {
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
- enforceLoweringOutcomePolicy(loweringOutcomes, graph.root.compile.unsupported);
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 loweringOutcomesWithDiagnostics = attachDiagnosticsToLoweringOutcomes(loweringOutcomes, instructionDiagnostics);
13982
- const rendered = withPersistedLoweringOutcomes(renderedWithoutOutcomeMetadata, loweringOutcomesWithDiagnostics);
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, loweringOutcomesWithDiagnostics, withBackupSummary(writeSummary(writtenPaths2, deletedPaths2), safety2.backup));
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, loweringOutcomesWithDiagnostics, withBackupSummary(writeSummary(writtenPaths, deletedPaths), safety.backup));
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 loweringOutcomes = collectLoweringOutcomes(graph, allRendered, {
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
- enforceLoweringOutcomePolicy(loweringOutcomes, graph.root.compile.unsupported);
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 loweringOutcomesWithDiagnostics = attachDiagnosticsToLoweringOutcomes(loweringOutcomes, instructionDiagnostics);
14024
- const rendered = withPersistedLoweringOutcomes(renderedWithoutOutcomeMetadata, loweringOutcomesWithDiagnostics);
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
- loweringOutcomes: loweringOutcomesWithDiagnostics,
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 loweringOutcomes = collectLoweringOutcomes(graph, allRendered, {
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
- enforceLoweringOutcomePolicy(loweringOutcomes, graph.root.compile.unsupported);
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 loweringOutcomesWithDiagnostics = attachDiagnosticsToLoweringOutcomes(loweringOutcomes, instructionDiagnostics);
14093
- const rendered = withPersistedLoweringOutcomes(renderedWithoutOutcomeMetadata, loweringOutcomesWithDiagnostics);
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
- loweringOutcomes: loweringOutcomesWithDiagnostics,
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, loweringOutcomes, writes) {
14240
+ function buildResult(rendered, diagnostics, renderResults, writes) {
14157
14241
  return {
14158
14242
  data: rendered,
14159
14243
  diagnostics,
14160
- loweringOutcomes,
14244
+ renderResults,
14161
14245
  ok: true,
14162
14246
  operation: "build",
14163
14247
  writes
14164
14248
  };
14165
14249
  }
14166
- function attachDiagnosticsToLoweringOutcomes(loweringOutcomes, diagnostics) {
14250
+ function attachDiagnosticsToRenderResults(renderResults, diagnostics) {
14167
14251
  const outputDiagnostics = diagnostics.filter((diagnostic) => diagnostic.outputPath !== undefined);
14168
14252
  if (outputDiagnostics.length === 0)
14169
- return loweringOutcomes;
14170
- return loweringOutcomes.map((outcome) => {
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 defineLoweringOutcome({
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: lowering outcome diagnostic ref requires an output path");
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 withPersistedLoweringOutcomes(rendered, loweringOutcomes) {
14203
- if (loweringOutcomes.length === 0)
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 = loweringOutcomesForLock(file.path, lock, loweringOutcomes);
14293
+ const lockOutcomes = renderResultsForLock(file.path, lock, renderResults);
14210
14294
  const value = {
14211
14295
  ...lock,
14212
- ...lockOutcomes.length === 0 ? {} : { loweringOutcomes: lockOutcomes }
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 loweringOutcomesForLock(lockPath, lock, loweringOutcomes) {
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 loweringOutcomes.filter((outcome) => {
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 loweringOutcomes = collectLoweringOutcomes(graph, allRendered, {
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 matchedLoweringOutcomes = explainLoweringOutcomes(target, asSource, loweringOutcomes);
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, matchedLoweringOutcomes),
15194
- loweringOutcomes: matchedLoweringOutcomes,
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 matchedLoweringOutcomes = explainLoweringOutcomes(target, asGenerated, loweringOutcomes, {
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, matchedLoweringOutcomes),
15208
- loweringOutcomes: matchedLoweringOutcomes,
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 matchedLoweringOutcomes = explainLoweringOutcomes(target, prefixMatch, loweringOutcomes);
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, matchedLoweringOutcomes),
15220
- loweringOutcomes: matchedLoweringOutcomes,
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 = explainLoweringOutcomes(target, [], loweringOutcomes);
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
- loweringOutcomes: sourceOnlyOutcomes,
15232
- notes: [`Matched ${sourceOnlyOutcomes.length} lowering outcome(s) under this source path.`]
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
- loweringOutcomes: [],
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 loweringOutcomes2 = loweringOutcomesFromError(error);
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
- loweringOutcomes: loweringOutcomes2,
15280
- notableLoweringOutcomes: notableLoweringOutcomes(loweringOutcomes2),
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 loweringOutcomes = [];
15373
+ let renderResults = [];
15290
15374
  try {
15291
15375
  const diff = await diffSkillsetResult(rootPath, options);
15292
15376
  drift = diff.data;
15293
- loweringOutcomes = diff.loweringOutcomes;
15377
+ renderResults = diff.renderResults;
15294
15378
  } catch (error) {
15295
15379
  buildDiagnostics = diagnosticsFromError(error);
15296
15380
  buildError = errorMessage(error);
15297
- loweringOutcomes = loweringOutcomesFromError(error);
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 = notableLoweringOutcomes(loweringOutcomes);
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
- loweringOutcomes,
15308
- notableLoweringOutcomes: notable,
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 explainLoweringOutcomes(target, items, outcomes, options = {}) {
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 notableLoweringOutcomes(outcomes) {
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 loweringOutcomesFromError(error) {
15341
- return error instanceof SkillsetLoweringError ? error.loweringOutcomes : [];
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
- const rootConfigPath = join12(graph.sourcePath, ROOT_CONFIG_FILE2);
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 }];
@@ -16974,6 +17172,7 @@ async function validateChangeCheck(rootPath, status, entries, options) {
16974
17172
  entries,
16975
17173
  issues: issues.sort(compareIssues),
16976
17174
  ok: !issues.some((issue) => issue.severity === "error"),
17175
+ stackedEvidence: stackedEvidenceGroups(validEntries, context),
16977
17176
  status
16978
17177
  };
16979
17178
  }
@@ -17117,6 +17316,28 @@ function findDuplicateIds(entries) {
17117
17316
  }
17118
17317
  return new Set([...counts].filter(([, count]) => count > 1).map(([id]) => id));
17119
17318
  }
17319
+ function stackedEvidenceGroups(entries, context) {
17320
+ const groups = new Map;
17321
+ for (const entry of entries) {
17322
+ for (const scope of entry.scopes) {
17323
+ const sourceHash = expectedHashForScope(scope, context);
17324
+ if (sourceHash === undefined || !(entry.sourceHashes.get(scope) ?? []).includes(sourceHash))
17325
+ continue;
17326
+ const key = `${scope}\x00${sourceHash}`;
17327
+ const existing = groups.get(key);
17328
+ if (existing === undefined) {
17329
+ groups.set(key, { paths: new Set([entry.path]), scope, sourceHash });
17330
+ continue;
17331
+ }
17332
+ existing.paths.add(entry.path);
17333
+ }
17334
+ }
17335
+ return [...groups.values()].filter((group) => group.paths.size > 1).map((group) => ({
17336
+ paths: [...group.paths].sort(compareStrings),
17337
+ scope: group.scope,
17338
+ sourceHash: group.sourceHash
17339
+ })).sort((left, right) => compareStrings(`${left.scope}\x00${left.sourceHash}`, `${right.scope}\x00${right.sourceHash}`));
17340
+ }
17120
17341
  function hasSeverityBearingRegion(regions) {
17121
17342
  return regions?.some((region) => region.severityBearing) === true;
17122
17343
  }
@@ -17237,12 +17458,12 @@ async function exists8(path2) {
17237
17458
  }
17238
17459
 
17239
17460
  // apps/skillset/src/adopt.ts
17240
- import { mkdtemp as mkdtemp3, mkdir as mkdir6, readFile as readFile16, rm as rm5, stat as stat14, writeFile as writeFile6 } from "fs/promises";
17461
+ import { mkdtemp as mkdtemp3, mkdir as mkdir7, readFile as readFile16, rm as rm5, stat as stat14, writeFile as writeFile7 } from "fs/promises";
17241
17462
  import { tmpdir as tmpdir2 } from "os";
17242
17463
  import { basename as basename7, dirname as dirname12, join as join17, relative as relative15, resolve as resolve7 } from "path";
17243
17464
 
17244
17465
  // apps/skillset/src/import.ts
17245
- import { mkdir as mkdir4, mkdtemp as mkdtemp2, readdir as readdir5, readFile as readFile14, realpath, rename, rm as rm4, stat as stat12, writeFile as writeFile4 } from "fs/promises";
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";
17246
17467
  import { homedir } from "os";
17247
17468
  import { basename as basename5, dirname as dirname10, join as join15, relative as relative13, resolve as resolve5 } from "path";
17248
17469
 
@@ -17250,7 +17471,7 @@ import { basename as basename5, dirname as dirname10, join as join15, relative a
17250
17471
  import { stat as stat11 } from "fs/promises";
17251
17472
  import { join as join14 } from "path";
17252
17473
  var ROOT_CONFIG_FILE3 = "config.yaml";
17253
- var NO_SOURCE_MESSAGE = "skillset: no source plugins, skills, instructions, project agents, or target-native islands found";
17474
+ var NO_SOURCE_MESSAGE = "skillset: no source plugins, skills, rules, project agents, or provider source found";
17254
17475
  async function seedReleaseBaselines(rootPath, options = {}, seedOptions = {}) {
17255
17476
  const sourceDir = options.sourceDir ?? ".skillset";
17256
17477
  const configPath = resolveInside(rootPath, join14(sourceDir, ROOT_CONFIG_FILE3));
@@ -17385,6 +17606,9 @@ async function exists9(path2) {
17385
17606
 
17386
17607
  // apps/skillset/src/import.ts
17387
17608
  var DEFAULT_SOURCE_DIR2 = ".skillset";
17609
+ var SOURCE_ROOT_DIR3 = "src";
17610
+ var PLUGINS_DIR2 = "plugins";
17611
+ var SKILLS_DIR2 = "skills";
17388
17612
  var RECOGNIZED_SOURCE_KEYS = new Set([
17389
17613
  "agents",
17390
17614
  "allowed_tools",
@@ -17433,7 +17657,7 @@ async function importSources(options) {
17433
17657
  files: imports.reduce((total, report) => total + report.files, 0),
17434
17658
  imports,
17435
17659
  kind: plan.kind,
17436
- loweringOutcomes: imports.flatMap((report) => report.loweringOutcomes),
17660
+ renderResults: imports.flatMap((report) => report.renderResults),
17437
17661
  ...options.provider === undefined ? {} : { provider: options.provider },
17438
17662
  sourcePath,
17439
17663
  warnings: plan.warnings
@@ -17443,12 +17667,12 @@ async function importSource(options) {
17443
17667
  const sourcePath = resolve5(options.sourcePath);
17444
17668
  const sourceDir = options.sourceDir ?? DEFAULT_SOURCE_DIR2;
17445
17669
  const name = await resolveImportName(sourcePath, options);
17446
- const targetPath = resolveInside(options.rootPath, join15(sourceDir, options.kind === "plugin" ? "plugins" : "skills", name));
17670
+ const targetPath = resolveInside(options.rootPath, join15(sourceDir, SOURCE_ROOT_DIR3, options.kind === "plugin" ? PLUGINS_DIR2 : SKILLS_DIR2, name));
17447
17671
  if (await exists10(targetPath)) {
17448
17672
  throw new Error(`skillset: import target already exists: ${targetPath}. ` + "Import never overwrites; remove the existing source or import under a different --name.");
17449
17673
  }
17450
17674
  const targetParent = dirname10(targetPath);
17451
- await mkdir4(targetParent, { recursive: true });
17675
+ await mkdir5(targetParent, { recursive: true });
17452
17676
  const stagingPath = await mkdtemp2(join15(targetParent, `.${basename5(targetPath)}.tmp-`));
17453
17677
  let committed = false;
17454
17678
  try {
@@ -17461,7 +17685,7 @@ async function importSource(options) {
17461
17685
  if (await exists10(targetPath)) {
17462
17686
  throw new Error(`skillset: import target already exists: ${targetPath}. ` + "Import never overwrites; remove the existing source or import under a different --name.");
17463
17687
  }
17464
- await rename(stagingPath, targetPath);
17688
+ await rename2(stagingPath, targetPath);
17465
17689
  committed = true;
17466
17690
  let baselineReport;
17467
17691
  try {
@@ -17480,7 +17704,7 @@ async function importSource(options) {
17480
17704
  files: copiedFiles.length,
17481
17705
  inferredSourceFields: classification.recognized,
17482
17706
  kind: options.kind,
17483
- loweringOutcomes: importLoweringOutcomes({
17707
+ renderResults: importRenderResults({
17484
17708
  classification,
17485
17709
  kind: options.kind,
17486
17710
  name,
@@ -17538,13 +17762,14 @@ function importWarnings(classification) {
17538
17762
  }
17539
17763
  return warnings;
17540
17764
  }
17541
- function importLoweringOutcomes(args) {
17765
+ function importRenderResults(args) {
17542
17766
  const toolPolicyFields = args.classification.targetNative.filter(isClaudeToolPolicyField);
17543
17767
  if (toolPolicyFields.length === 0)
17544
17768
  return [];
17545
17769
  const sourcePath = importSourcePath(args.rootPath, args.targetPath, args.kind);
17546
17770
  return [
17547
- defineLoweringOutcome({
17771
+ defineRenderResult({
17772
+ destination: "skill-frontmatter",
17548
17773
  diagnostics: [
17549
17774
  {
17550
17775
  code: "import-preserved-target-native-frontmatter",
@@ -17609,8 +17834,8 @@ async function copyImportSource(sourcePath, targetPath, kind, name) {
17609
17834
  const copied = [];
17610
17835
  for (const file of await collectFiles6(copyRoot)) {
17611
17836
  const relativePath2 = relativeImportPath(copyRoot, file, kind);
17612
- await mkdir4(dirname10(join15(targetPath, relativePath2)), { recursive: true });
17613
- await writeFile4(join15(targetPath, relativePath2), await readFile14(file));
17837
+ await mkdir5(dirname10(join15(targetPath, relativePath2)), { recursive: true });
17838
+ await writeFile5(join15(targetPath, relativePath2), await readFile14(file));
17614
17839
  copied.push(relativePath2);
17615
17840
  }
17616
17841
  if (kind === "plugin" && !await exists10(join15(targetPath, "skillset.yaml"))) {
@@ -17631,11 +17856,11 @@ async function stampImportedOrigins(targetPath, sourcePath, copiedFiles, kind, s
17631
17856
  }
17632
17857
  async function writeYamlSourceOrigin(path2, origin) {
17633
17858
  const config2 = parseYamlRecord(await readFile14(path2, "utf8"), path2);
17634
- await writeFile4(path2, stringifyYaml(withSkillsetOrigin(config2, origin)));
17859
+ await writeFile5(path2, stringifyYaml(withSkillsetOrigin(config2, origin)));
17635
17860
  }
17636
17861
  async function writeMarkdownSourceOrigin(path2, origin) {
17637
17862
  const parts = parseMarkdown(await readFile14(path2, "utf8"), path2);
17638
- await writeFile4(path2, stringifyMarkdown(withSkillsetOrigin(parts.frontmatter, origin), parts.body));
17863
+ await writeFile5(path2, stringifyMarkdown(withSkillsetOrigin(parts.frontmatter, origin), parts.body));
17639
17864
  }
17640
17865
  function withSkillsetOrigin(record, origin) {
17641
17866
  const existing = isJsonRecord(record.skillset) ? record.skillset : {};
@@ -17676,7 +17901,7 @@ async function resolvePluginConfig(sourcePath) {
17676
17901
  return;
17677
17902
  }
17678
17903
  async function collectFiles6(root) {
17679
- const entries = await readdir5(root, { withFileTypes: true });
17904
+ const entries = await readdir6(root, { withFileTypes: true });
17680
17905
  const files = [];
17681
17906
  for (const entry of entries.sort((left, right) => compareStrings(left.name, right.name))) {
17682
17907
  const path2 = join15(root, entry.name);
@@ -17782,7 +18007,7 @@ async function importChildren(sourcePath, kind, predicate) {
17782
18007
  const stats = await stat12(sourcePath);
17783
18008
  if (!stats.isDirectory())
17784
18009
  return [];
17785
- const entries = await readdir5(sourcePath, { withFileTypes: true });
18010
+ const entries = await readdir6(sourcePath, { withFileTypes: true });
17786
18011
  const seen = new Set;
17787
18012
  const items = [];
17788
18013
  for (const entry of entries.sort((left, right) => compareStrings(left.name, right.name))) {
@@ -17816,7 +18041,7 @@ async function writeImportedPluginConfig(targetPath, name) {
17816
18041
  license: nativeManifest.license,
17817
18042
  keywords: nativeManifest.keywords
17818
18043
  };
17819
- await writeFile4(join15(targetPath, "skillset.yaml"), stringifyYaml({
18044
+ await writeFile5(join15(targetPath, "skillset.yaml"), stringifyYaml({
17820
18045
  skillset: metadata
17821
18046
  }));
17822
18047
  }
@@ -17845,7 +18070,7 @@ async function exists10(path2) {
17845
18070
  }
17846
18071
  }
17847
18072
  // apps/skillset/src/setup.ts
17848
- import { mkdir as mkdir5, readdir as readdir6, readFile as readFile15, realpath as realpath2, stat as stat13, writeFile as writeFile5 } from "fs/promises";
18073
+ import { mkdir as mkdir6, readdir as readdir7, readFile as readFile15, realpath as realpath2, stat as stat13, writeFile as writeFile6 } from "fs/promises";
17849
18074
  import { basename as basename6, dirname as dirname11, join as join16, relative as relative14, resolve as resolve6 } from "path";
17850
18075
 
17851
18076
  // apps/skillset/src/ci.ts
@@ -18073,6 +18298,16 @@ function renderCiWorkflow() {
18073
18298
  var DEFAULT_CREATE_NAME = "my-skillset";
18074
18299
  var DEFAULT_GLOBAL_SOURCE = ".skillset/src";
18075
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
+ ];
18076
18311
  async function initSkillset(options = {}) {
18077
18312
  const rootPath = await initRootPath(options);
18078
18313
  return applySetupPlan("init", rootPath, options);
@@ -18087,7 +18322,7 @@ async function createSkillset(options = {}) {
18087
18322
  if (!stats.isDirectory()) {
18088
18323
  throw new Error(`skillset: create target exists and is not a directory: ${rootPath}`);
18089
18324
  }
18090
- const entries = await readdir6(rootPath);
18325
+ const entries = await readdir7(rootPath);
18091
18326
  if (entries.length > 0) {
18092
18327
  throw new Error(`skillset: create target must be empty: ${rootPath}`);
18093
18328
  }
@@ -18113,6 +18348,11 @@ async function applySetupPlan(kind, rootPath, options) {
18113
18348
  files.push({ path: file.path, status: "exists" });
18114
18349
  continue;
18115
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
+ }
18116
18356
  if (file.path === CI_WORKFLOW_PATH) {
18117
18357
  files.push({ path: file.path, status: "exists" });
18118
18358
  continue;
@@ -18127,8 +18367,8 @@ async function applySetupPlan(kind, rootPath, options) {
18127
18367
  const existing = await readExistingFile(absolutePath);
18128
18368
  if (existing !== undefined)
18129
18369
  continue;
18130
- await mkdir5(dirname11(absolutePath), { recursive: true });
18131
- await writeFile5(absolutePath, file.content);
18370
+ await mkdir6(dirname11(absolutePath), { recursive: true });
18371
+ await writeFile6(absolutePath, file.content);
18132
18372
  }
18133
18373
  if (git?.status === "create")
18134
18374
  await initializeGit(rootPath);
@@ -18174,7 +18414,11 @@ async function gitRoot(cwd) {
18174
18414
  }
18175
18415
  async function validateExistingRootConfig(path2) {
18176
18416
  const content = await readFile15(path2, "utf8");
18177
- validateConfigDocument(parseYamlRecord(content, path2), path2, { allowCompile: true });
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);
18178
18422
  }
18179
18423
  var GENERATED_INSTRUCTIONS_MARKER = "<!-- Generated by skillset";
18180
18424
  var ROOT_INSTRUCTION_FILES = ["AGENTS.md", "CLAUDE.md"];
@@ -18211,7 +18455,7 @@ async function nestedPluginSources(rootPath) {
18211
18455
  return [];
18212
18456
  const realRoot = await realpath2(rootPath);
18213
18457
  const sources = [];
18214
- for (const entry of (await readdir6(pluginsPath)).sort()) {
18458
+ for (const entry of (await readdir7(pluginsPath)).sort()) {
18215
18459
  const absolutePath = join16(pluginsPath, entry);
18216
18460
  if (!await pathExists(absolutePath))
18217
18461
  continue;
@@ -18256,17 +18500,17 @@ async function detectSurveySkips(rootPath) {
18256
18500
  relativeTargetPath: "agents",
18257
18501
  target: "claude"
18258
18502
  }));
18259
- await maybeSkip(skips, rootPath, ".claude/rules", "rules", "rules are not importable yet; adopt will lower them to .skillset/instructions/ in the transform milestone", surveySkipOutcome({
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({
18260
18504
  featureId: "project-instructions",
18261
18505
  path: ".claude/rules",
18262
- reason: "rules are not importable yet; adopt will lower them to .skillset/instructions/ in the transform milestone",
18506
+ reason: "rules are not importable yet; adopt will lower them to .skillset/src/rules/ in the transform milestone",
18263
18507
  relativeTargetPath: "rules",
18264
18508
  target: "claude"
18265
18509
  }));
18266
18510
  if (await hasNonSkillCodexContent(rootPath)) {
18267
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";
18268
18512
  skips.push({
18269
- loweringOutcome: surveySkipOutcome({
18513
+ renderResult: surveySkipOutcome({
18270
18514
  featureId: "target-native-islands",
18271
18515
  path: ".codex",
18272
18516
  reason,
@@ -18281,7 +18525,7 @@ async function detectSurveySkips(rootPath) {
18281
18525
  for (const path2 of await foreignPluginManifests(rootPath)) {
18282
18526
  const reason = "plugin manifest for an unsupported target; skillset can only represent claude and codex surfaces";
18283
18527
  skips.push({
18284
- loweringOutcome: foreignManifestSkipOutcome(path2, reason),
18528
+ renderResult: foreignManifestSkipOutcome(path2, reason),
18285
18529
  path: path2,
18286
18530
  reason,
18287
18531
  surface: "foreign-manifest"
@@ -18289,7 +18533,7 @@ async function detectSurveySkips(rootPath) {
18289
18533
  }
18290
18534
  return skips.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
18291
18535
  }
18292
- async function maybeSkip(skips, rootPath, path2, surface, reason, loweringOutcome) {
18536
+ async function maybeSkip(skips, rootPath, path2, surface, reason, renderResult) {
18293
18537
  const absolutePath = join16(rootPath, path2);
18294
18538
  if (!await pathExists(absolutePath))
18295
18539
  return;
@@ -18297,13 +18541,14 @@ async function maybeSkip(skips, rootPath, path2, surface, reason, loweringOutcom
18297
18541
  return;
18298
18542
  if (await isManagedCandidate(absolutePath))
18299
18543
  return;
18300
- const entries = await readdir6(absolutePath);
18544
+ const entries = await readdir7(absolutePath);
18301
18545
  if (entries.filter((entry) => entry !== ".DS_Store").length === 0)
18302
18546
  return;
18303
- skips.push({ ...loweringOutcome === undefined ? {} : { loweringOutcome }, path: path2, reason, surface });
18547
+ skips.push({ ...renderResult === undefined ? {} : { renderResult }, path: path2, reason, surface });
18304
18548
  }
18305
18549
  function surveySkipOutcome(args) {
18306
- return defineLoweringOutcome({
18550
+ return defineRenderResult({
18551
+ destination: "target-native-island",
18307
18552
  diagnostics: [
18308
18553
  {
18309
18554
  code: "adoption-survey-skip",
@@ -18321,7 +18566,7 @@ function surveySkipOutcome(args) {
18321
18566
  });
18322
18567
  }
18323
18568
  function foreignManifestSkipOutcome(path2, reason) {
18324
- return defineLoweringOutcome({
18569
+ return defineRenderResult({
18325
18570
  diagnostics: [{ code: "adoption-survey-skip", message: reason, path: path2 }],
18326
18571
  featureId: "runtime-adapters",
18327
18572
  policy: "default",
@@ -18342,12 +18587,12 @@ async function hasNonSkillCodexContent(rootPath) {
18342
18587
  return false;
18343
18588
  if (await isManagedCandidate(codexPath))
18344
18589
  return false;
18345
- const entries = await readdir6(codexPath);
18590
+ const entries = await readdir7(codexPath);
18346
18591
  return entries.some((entry) => entry !== "skills" && entry !== ".DS_Store");
18347
18592
  }
18348
18593
  async function foreignPluginManifests(rootPath) {
18349
18594
  const paths = [];
18350
- for (const entry of (await readdir6(rootPath)).sort()) {
18595
+ for (const entry of (await readdir7(rootPath)).sort()) {
18351
18596
  if (NATIVE_PLUGIN_MANIFEST_DIRS.has(entry))
18352
18597
  continue;
18353
18598
  if (!/^\.[a-z][a-z0-9]*-plugin$/.test(entry))
@@ -18412,7 +18657,7 @@ async function maybeCandidate(candidates, rootPath, path2, kind) {
18412
18657
  return;
18413
18658
  if (await isManagedCandidate(absolutePath))
18414
18659
  return;
18415
- const entries = await readdir6(absolutePath);
18660
+ const entries = await readdir7(absolutePath);
18416
18661
  if (entries.filter((entry) => entry !== ".DS_Store").length === 0)
18417
18662
  return;
18418
18663
  candidates.push({ kind, path: relative14(rootPath, absolutePath).replaceAll("\\", "/") });
@@ -18427,12 +18672,20 @@ function setupFiles(options) {
18427
18672
  const files = [
18428
18673
  {
18429
18674
  path: ".skillset/config.yaml",
18430
- content: rootConfig(options.name, options.targets)
18675
+ content: rootConfig(options.targets)
18676
+ },
18677
+ {
18678
+ path: `${SETUP_SOURCE_DIR}/skillset.yaml`,
18679
+ content: rootSourceManifest(options.name)
18431
18680
  },
18432
18681
  {
18433
18682
  path: `${SETUP_SOURCE_DIR}/.gitkeep`,
18434
18683
  content: ""
18435
- }
18684
+ },
18685
+ ...SETUP_SOURCE_PLACEHOLDERS.map((directory) => ({
18686
+ path: `${SETUP_SOURCE_DIR}/${directory}/.gitkeep`,
18687
+ content: ""
18688
+ }))
18436
18689
  ];
18437
18690
  if (options.kind === "create" && options.global !== true) {
18438
18691
  files.unshift({
@@ -18444,12 +18697,6 @@ function setupFiles(options) {
18444
18697
  });
18445
18698
  }
18446
18699
  const include = options.include ?? [];
18447
- if (include.includes("agents")) {
18448
- files.push({
18449
- path: `${SETUP_SOURCE_DIR}/agents/.gitkeep`,
18450
- content: ""
18451
- });
18452
- }
18453
18700
  if (include.includes("ci")) {
18454
18701
  files.push({ path: CI_WORKFLOW_PATH, content: renderCiWorkflow() });
18455
18702
  }
@@ -18464,7 +18711,7 @@ async function setupGit(kind, rootPath, options) {
18464
18711
  };
18465
18712
  }
18466
18713
  async function initializeGit(rootPath) {
18467
- await mkdir5(rootPath, { recursive: true });
18714
+ await mkdir6(rootPath, { recursive: true });
18468
18715
  const proc = Bun.spawn({
18469
18716
  cmd: ["git", "init", "-q"],
18470
18717
  cwd: rootPath,
@@ -18482,12 +18729,10 @@ async function initializeGit(rootPath) {
18482
18729
  ${stdout}${stderr}`.trim());
18483
18730
  }
18484
18731
  }
18485
- function rootConfig(name, targets) {
18732
+ function rootConfig(targets) {
18486
18733
  const targetLines = targets.map((target) => ` - ${target}`).join(`
18487
18734
  `);
18488
18735
  return [
18489
- "skillset:",
18490
- ` name: ${name}`,
18491
18736
  "compile:",
18492
18737
  " targets:",
18493
18738
  targetLines,
@@ -18495,11 +18740,19 @@ function rootConfig(name, targets) {
18495
18740
  ].join(`
18496
18741
  `);
18497
18742
  }
18743
+ function rootSourceManifest(name) {
18744
+ return [
18745
+ "skillset:",
18746
+ ` name: ${name}`,
18747
+ ""
18748
+ ].join(`
18749
+ `);
18750
+ }
18498
18751
  function createReadme(name, targets) {
18499
18752
  return [
18500
18753
  `# ${name}`,
18501
18754
  "",
18502
- "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.",
18503
18756
  "",
18504
18757
  "## Quick Start",
18505
18758
  "",
@@ -18512,10 +18765,11 @@ function createReadme(name, targets) {
18512
18765
  "",
18513
18766
  "## Layout",
18514
18767
  "",
18515
- "- `.skillset/config.yaml` selects compile targets and source settings.",
18516
- "- `.skillset/src/` is the portable project source area for instructions, agents, and target-native islands.",
18517
- "- `.skillset/plugins/` holds plugin source when this repo authors marketplace plugins.",
18518
- "- `.skillset/skills/` holds standalone skill source when this repo authors repo-local or user skill roots.",
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.",
18519
18773
  "",
18520
18774
  `Default compile targets: ${targets.join(", ")}.`,
18521
18775
  ""
@@ -18530,7 +18784,8 @@ function createAgentsGuide(name) {
18530
18784
  "",
18531
18785
  "## Working Rules",
18532
18786
  "",
18533
- "- Treat `.skillset/` as editable source.",
18787
+ "- Treat `.skillset/src/` as editable source.",
18788
+ "- Treat `.skillset/config.yaml` as workspace/build configuration.",
18534
18789
  "- Treat generated target directories as outputs; do not hand-edit them as source truth.",
18535
18790
  "- Run `skillset build --dry-run` before writing generated outputs.",
18536
18791
  "- Run `skillset check` before committing source changes.",
@@ -18597,7 +18852,7 @@ function isErrno2(error, code) {
18597
18852
 
18598
18853
  // apps/skillset/src/adopt.ts
18599
18854
  var ADOPT_REPORT_DIR = ".skillset/build/adopt";
18600
- var INSTRUCTIONS_DIR2 = ".skillset/instructions";
18855
+ var INSTRUCTIONS_DIR = ".skillset/src/rules";
18601
18856
  async function adoptSkillset(source2, options = {}) {
18602
18857
  const { cwd, targets, write, ...buildOptions } = options;
18603
18858
  const acquisition = await acquireAdoptSource(source2, cwd ?? process.cwd());
@@ -18628,7 +18883,7 @@ async function adoptResolvedRoot(acquisition, options = {}) {
18628
18883
  cutover: [],
18629
18884
  imports: [],
18630
18885
  lintIssues: [],
18631
- loweringOutcomes: surveySkipLoweringOutcomes(init.surveySkips),
18886
+ renderResults: surveySkipRenderResults(init.surveySkips),
18632
18887
  ok: true,
18633
18888
  rootPath: init.rootPath,
18634
18889
  setupFiles: init.files,
@@ -18653,17 +18908,17 @@ async function adoptResolvedRoot(acquisition, options = {}) {
18653
18908
  buildError = errorMessage3(error);
18654
18909
  }
18655
18910
  let builtFiles = 0;
18656
- let loweringOutcomes = [
18657
- ...surveySkipLoweringOutcomes(init.surveySkips),
18658
- ...imports.flatMap((result) => result.loweringOutcomes)
18911
+ let renderResults = [
18912
+ ...surveySkipRenderResults(init.surveySkips),
18913
+ ...imports.flatMap((result) => result.renderResults)
18659
18914
  ];
18660
18915
  if (buildError === undefined) {
18661
18916
  try {
18662
18917
  const build2 = await buildSkillsetResult(init.rootPath, { ...buildOptions, isolated: true });
18663
18918
  builtFiles = build2.data.length;
18664
- loweringOutcomes = [
18665
- ...loweringOutcomes,
18666
- ...build2.loweringOutcomes
18919
+ renderResults = [
18920
+ ...renderResults,
18921
+ ...build2.renderResults
18667
18922
  ];
18668
18923
  } catch (error) {
18669
18924
  buildError = errorMessage3(error);
@@ -18680,7 +18935,7 @@ async function adoptResolvedRoot(acquisition, options = {}) {
18680
18935
  cutover,
18681
18936
  imports,
18682
18937
  lintIssues,
18683
- loweringOutcomes,
18938
+ renderResults,
18684
18939
  ok: imports.every((result) => result.ok) && lintErrors.length === 0 && buildError === undefined,
18685
18940
  rootPath: init.rootPath,
18686
18941
  setupFiles: init.files,
@@ -18689,14 +18944,14 @@ async function adoptResolvedRoot(acquisition, options = {}) {
18689
18944
  write: true
18690
18945
  };
18691
18946
  const reportDir = join17(init.rootPath, ADOPT_REPORT_DIR);
18692
- await mkdir6(reportDir, { recursive: true });
18693
- await writeFile6(join17(reportDir, "report.md"), renderAdoptReportMarkdown(report, { rootPath: init.rootPath }));
18694
- await writeFile6(join17(reportDir, "report.json"), `${JSON.stringify(report, null, 2)}
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)}
18695
18950
  `);
18696
18951
  return report;
18697
18952
  }
18698
- function surveySkipLoweringOutcomes(skips) {
18699
- return skips.flatMap((skip) => skip.loweringOutcome === undefined ? [] : [skip.loweringOutcome]);
18953
+ function surveySkipRenderResults(skips) {
18954
+ return skips.flatMap((skip) => skip.renderResult === undefined ? [] : [skip.renderResult]);
18700
18955
  }
18701
18956
  async function acquireAdoptSource(source2, cwd) {
18702
18957
  const localPath = resolve7(cwd, source2);
@@ -18740,9 +18995,9 @@ async function importCandidate(rootPath, acquisition, candidate, cutover, previe
18740
18995
  await writeMarkdownSourceOrigin2(join17(rootPath, destination), sourceOriginFor(acquisition, candidate.path));
18741
18996
  cutover.push(candidate.path);
18742
18997
  previewSources.push(destination);
18743
- return { candidate, destination, detail: destination, loweringOutcomes: [], ok: true, units: [] };
18998
+ return { candidate, destination, detail: destination, renderResults: [], ok: true, units: [] };
18744
18999
  } catch (error) {
18745
- return { candidate, detail: errorMessage3(error), loweringOutcomes: [], ok: false, units: [] };
19000
+ return { candidate, detail: errorMessage3(error), renderResults: [], ok: false, units: [] };
18746
19001
  }
18747
19002
  }
18748
19003
  try {
@@ -18770,23 +19025,23 @@ async function importCandidate(rootPath, acquisition, candidate, cutover, previe
18770
19025
  return {
18771
19026
  candidate,
18772
19027
  detail: `${units.map((unit) => `${unit.kind} ${unit.name}`).join(", ")} (${batch.files} files)`,
18773
- loweringOutcomes: batch.loweringOutcomes,
19028
+ renderResults: batch.renderResults,
18774
19029
  ok: true,
18775
19030
  units
18776
19031
  };
18777
19032
  } catch (error) {
18778
- return { candidate, detail: errorMessage3(error), loweringOutcomes: [], ok: false, units: [] };
19033
+ return { candidate, detail: errorMessage3(error), renderResults: [], ok: false, units: [] };
18779
19034
  }
18780
19035
  }
18781
19036
  async function importInstructionFile(rootPath, sourceName) {
18782
- const destinationRelative = `${INSTRUCTIONS_DIR2}/${sourceName.toLowerCase()}`;
19037
+ const destinationRelative = `${INSTRUCTIONS_DIR}/${sourceName.toLowerCase()}`;
18783
19038
  const destination = join17(rootPath, destinationRelative);
18784
19039
  if (await exists11(destination)) {
18785
19040
  throw new Error(`skillset: instructions import target already exists: ${destinationRelative}. ` + "Adopt never overwrites; remove the existing file or merge by hand.");
18786
19041
  }
18787
19042
  const content = await readFile16(join17(rootPath, sourceName));
18788
- await mkdir6(dirname12(destination), { recursive: true });
18789
- await writeFile6(destination, content);
19043
+ await mkdir7(dirname12(destination), { recursive: true });
19044
+ await writeFile7(destination, content);
18790
19045
  return destinationRelative;
18791
19046
  }
18792
19047
  function sourceOriginFor(acquisition, path2) {
@@ -18799,7 +19054,7 @@ function relativeOriginPath(rootPath, sourcePath, copiedFile) {
18799
19054
  }
18800
19055
  async function writeMarkdownSourceOrigin2(path2, origin) {
18801
19056
  const parts = parseMarkdown(await readFile16(path2, "utf8"), path2);
18802
- await writeFile6(path2, stringifyMarkdown(withSkillsetOrigin2(parts.frontmatter, origin), parts.body));
19057
+ await writeFile7(path2, stringifyMarkdown(withSkillsetOrigin2(parts.frontmatter, origin), parts.body));
18803
19058
  }
18804
19059
  function withSkillsetOrigin2(record, origin) {
18805
19060
  const existing = isJsonRecord(record.skillset) ? record.skillset : {};
@@ -18859,7 +19114,7 @@ dialect: claude
18859
19114
  ---
18860
19115
 
18861
19116
  ${raw}`;
18862
- await writeFile6(path2, updated);
19117
+ await writeFile7(path2, updated);
18863
19118
  return true;
18864
19119
  }
18865
19120
  function markdownBody(raw, label) {
@@ -18881,7 +19136,7 @@ function renderAdoptReportMarkdown(report, opts) {
18881
19136
  if (report.alreadyAdopted) {
18882
19137
  lines.push("- note: the repo already had `.skillset/config.yaml`; adoption proceeded against the existing source tree");
18883
19138
  }
18884
- 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", `- lowering outcomes: ${report.loweringOutcomes.length}`, "");
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}`, "");
18885
19140
  lines.push("## Acquisition", "");
18886
19141
  if (report.acquisition.kind === "git") {
18887
19142
  lines.push("- source: git remote", `- repo: \`${report.acquisition.repo}\``, `- ref: \`${report.acquisition.ref}\``, `- clone: \`${report.acquisition.rootPath}\``, "");
@@ -18970,15 +19225,15 @@ function renderAdoptReportMarkdown(report, opts) {
18970
19225
  } else {
18971
19226
  lines.push("```", report.buildError.trimEnd(), "```", "");
18972
19227
  }
18973
- lines.push("### Lowering outcomes", "");
18974
- if (report.loweringOutcomes.length === 0) {
18975
- lines.push("No lowering outcomes recorded.", "");
19228
+ lines.push("### Render results", "");
19229
+ if (report.renderResults.length === 0) {
19230
+ lines.push("No render results recorded.", "");
18976
19231
  } else {
18977
- for (const summary of summarizeLoweringOutcomes(report.loweringOutcomes)) {
19232
+ for (const summary of summarizeRenderResults(report.renderResults)) {
18978
19233
  lines.push(`- ${summary}`);
18979
19234
  }
18980
19235
  lines.push("");
18981
- lines.push("Full structured lowering outcomes are in `report.json` and in the isolated `.skillset.lock` files when the isolated build completes.", "");
19236
+ lines.push("Full structured render results are in `report.json` and in the isolated `.skillset.lock` files when the isolated build completes.", "");
18982
19237
  }
18983
19238
  lines.push("## Cutover", "");
18984
19239
  lines.push(`1. Review the generated mirror under \`${ISOLATED_OUT_ROOT}/\` against the originals.`);
@@ -18996,7 +19251,7 @@ function renderAdoptReportMarkdown(report, opts) {
18996
19251
  `).trimEnd()}
18997
19252
  `;
18998
19253
  }
18999
- function summarizeLoweringOutcomes(outcomes) {
19254
+ function summarizeRenderResults(outcomes) {
19000
19255
  const counts = new Map;
19001
19256
  for (const outcome of outcomes) {
19002
19257
  const key = `${outcome.target ?? "workspace"} ${outcome.status}`;
@@ -19036,7 +19291,7 @@ async function exists11(path2) {
19036
19291
 
19037
19292
  // apps/skillset/src/change-workflow.ts
19038
19293
  import { createHash as createHash6, randomBytes } from "crypto";
19039
- import { mkdir as mkdir7, readFile as readFile17, stat as stat15, writeFile as writeFile7 } from "fs/promises";
19294
+ import { mkdir as mkdir8, readFile as readFile17, stat as stat15, writeFile as writeFile8 } from "fs/promises";
19040
19295
  import { isAbsolute as isAbsolute2, join as join18, resolve as resolve8 } from "path";
19041
19296
  var PENDING_DIR2 = "changes/pending";
19042
19297
  var HISTORY_FILE2 = "changes/history.jsonl";
@@ -19070,8 +19325,8 @@ async function addChangeEntry(rootPath, options) {
19070
19325
  scopes,
19071
19326
  sourceHashes
19072
19327
  });
19073
- await mkdir7(resolveInside(rootPath, join18(sourceDir, PENDING_DIR2)), { recursive: true });
19074
- await writeFile7(absolutePath, stringifyMarkdown(entryFrontmatter, reason), "utf8");
19328
+ await mkdir8(resolveInside(rootPath, join18(sourceDir, PENDING_DIR2)), { recursive: true });
19329
+ await writeFile8(absolutePath, stringifyMarkdown(entryFrontmatter, reason), "utf8");
19075
19330
  const [entry] = await readPendingChangeEntries(rootPath, statusOptions).then((entries) => entries.filter((item) => item.id === id));
19076
19331
  if (entry === undefined)
19077
19332
  throw new Error(`skillset: failed to read created change entry ${id}`);
@@ -19087,7 +19342,7 @@ async function updateChangeReason(rootPath, options) {
19087
19342
  const body = options.append ? `${parts.body.trimEnd()}
19088
19343
 
19089
19344
  ${newReason}` : newReason;
19090
- await writeFile7(absolutePath, stringifyMarkdown(parts.frontmatter, body), "utf8");
19345
+ await writeFile8(absolutePath, stringifyMarkdown(parts.frontmatter, body), "utf8");
19091
19346
  const updated = resolvePendingChangeRef(await readPendingChangeEntries(rootPath, options), entry.id ?? options.ref);
19092
19347
  const refs = refIndex([updated], await readHistoryEntries(rootPath, options));
19093
19348
  return { entry: pendingView(updated, refs) };
@@ -19823,10 +20078,10 @@ function renderAgentRuntimeSnippet(target) {
19823
20078
  // apps/skillset/src/runtime-hooks/source-gate.ts
19824
20079
  var HOOK_RELEVANT_SOURCE_PATHS = [
19825
20080
  ".skillset/config.yaml",
19826
- ".skillset/instructions",
19827
- ".skillset/skills",
19828
- ".skillset/plugins",
19829
- ".skillset/shared",
20081
+ ".skillset/src/rules",
20082
+ ".skillset/src/skills",
20083
+ ".skillset/src/plugins",
20084
+ ".skillset/src/shared",
19830
20085
  ".skillset/src",
19831
20086
  ".skillset/changes/pending"
19832
20087
  ];
@@ -19913,7 +20168,7 @@ function result(args) {
19913
20168
  };
19914
20169
  }
19915
20170
  // apps/skillset/src/release.ts
19916
- import { appendFile, mkdir as mkdir8, readFile as readFile19, rm as rm6, stat as stat17, writeFile as writeFile8 } from "fs/promises";
20171
+ import { appendFile, mkdir as mkdir9, readFile as readFile19, rm as rm6, stat as stat17, writeFile as writeFile9 } from "fs/promises";
19917
20172
  import { createHash as createHash7 } from "crypto";
19918
20173
  import { dirname as dirname13, join as join20 } from "path";
19919
20174
  var HISTORY_FILE3 = "changes/history.jsonl";
@@ -20119,7 +20374,7 @@ async function appendHistory(rootPath, sourceDir, entries, appliedAt, files) {
20119
20374
  return;
20120
20375
  const relativePath2 = join20(sourceDir, HISTORY_FILE3).replaceAll("\\", "/");
20121
20376
  const absolutePath = resolveInside(rootPath, relativePath2);
20122
- await mkdir8(dirname13(absolutePath), { recursive: true });
20377
+ await mkdir9(dirname13(absolutePath), { recursive: true });
20123
20378
  const lines = entries.flatMap((entry) => entry.id === undefined || entry.bump === undefined ? [] : [
20124
20379
  JSON.stringify({
20125
20380
  appliedAt,
@@ -20144,7 +20399,7 @@ async function appendReleaseRecord(rootPath, sourceDir, plan, appliedAt, files)
20144
20399
  return;
20145
20400
  const relativePath2 = join20(sourceDir, RELEASES_FILE).replaceAll("\\", "/");
20146
20401
  const absolutePath = resolveInside(rootPath, relativePath2);
20147
- await mkdir8(dirname13(absolutePath), { recursive: true });
20402
+ await mkdir9(dirname13(absolutePath), { recursive: true });
20148
20403
  await appendFile(absolutePath, `${JSON.stringify({
20149
20404
  appliedAt,
20150
20405
  baseline: { hashSchema: SOURCE_HASH_SCHEMA, kind: "source-hashes" },
@@ -20188,8 +20443,8 @@ async function restoreSnapshots(rootPath, snapshots) {
20188
20443
  await rm6(absolutePath, { force: true });
20189
20444
  continue;
20190
20445
  }
20191
- await mkdir8(dirname13(absolutePath), { recursive: true });
20192
- await writeFile8(absolutePath, snapshot.content);
20446
+ await mkdir9(dirname13(absolutePath), { recursive: true });
20447
+ await writeFile9(absolutePath, snapshot.content);
20193
20448
  }
20194
20449
  }
20195
20450
  async function exists14(path2) {
@@ -20233,7 +20488,7 @@ function releaseIdFor(scopes) {
20233
20488
  return hash.digest("hex").slice(0, 12);
20234
20489
  }
20235
20490
  // apps/skillset/src/test-runner.ts
20236
- import { cp, mkdir as mkdir9, mkdtemp as mkdtemp4, readFile as readFile20, rm as rm7, stat as stat18, writeFile as writeFile9 } from "fs/promises";
20491
+ import { cp, mkdir as mkdir10, mkdtemp as mkdtemp4, readFile as readFile20, rm as rm7, stat as stat18, writeFile as writeFile10 } from "fs/promises";
20237
20492
  import { createHash as createHash8, randomBytes as randomBytes2 } from "crypto";
20238
20493
  import { dirname as dirname14, join as join21, relative as relative16, resolve as resolve9 } from "path";
20239
20494
  import { tmpdir as tmpdir3 } from "os";
@@ -20264,7 +20519,7 @@ async function runSkillsetTest(rootPath, name, options = {}) {
20264
20519
  const workspaceLockPath = resolveInside(rootPath, ".skillset.lock");
20265
20520
  const ignoredSourceBuildPath = resolveInside(rootPath, join21(sourceDir, "build"));
20266
20521
  try {
20267
- await mkdir9(stagingWorkspacePath, { recursive: true });
20522
+ await mkdir10(stagingWorkspacePath, { recursive: true });
20268
20523
  await cp(sourcePath, stagingSourcePath, {
20269
20524
  filter: (path2) => !isSameOrInside2(ignoredSourceBuildPath, path2),
20270
20525
  recursive: true
@@ -20289,7 +20544,7 @@ async function runSkillsetTest(rootPath, name, options = {}) {
20289
20544
  if (assertions.every((assertion) => assertion.ok)) {
20290
20545
  await validateActivationExpectations(stagingWorkspacePath, declaration, buildOptions);
20291
20546
  }
20292
- await mkdir9(runPath, { recursive: true });
20547
+ await mkdir10(runPath, { recursive: true });
20293
20548
  await cp(stagingWorkspacePath, workspacePath, { recursive: true });
20294
20549
  const activationPath = await writeActivationProbes(runPath, declaration);
20295
20550
  const ok = assertions.every((assertion) => assertion.ok);
@@ -20314,8 +20569,8 @@ async function runSkillsetTest(rootPath, name, options = {}) {
20314
20569
  ...activationReport,
20315
20570
  workspacePath: relative16(rootPath, workspacePath)
20316
20571
  };
20317
- await writeFile9(reportPath, renderValidatedJson(report, relative16(rootPath, reportPath)), "utf8");
20318
- await writeFile9(reportMarkdownPath, renderMarkdownReport(report), "utf8");
20572
+ await writeFile10(reportPath, renderValidatedJson(report, relative16(rootPath, reportPath)), "utf8");
20573
+ await writeFile10(reportMarkdownPath, renderMarkdownReport(report), "utf8");
20319
20574
  await refreshLatest(buildRoot, runPath, latestPath, report, rootPath);
20320
20575
  return {
20321
20576
  assertions,
@@ -20580,16 +20835,16 @@ async function writeActivationProbes(runPath, declaration) {
20580
20835
  if (probes.length === 0)
20581
20836
  continue;
20582
20837
  const targetRoot = join21(activationRoot, target);
20583
- await mkdir9(targetRoot, { recursive: true });
20838
+ await mkdir10(targetRoot, { recursive: true });
20584
20839
  const records = probes.map((probe) => activationProbeRecord(probe, target));
20585
- await writeFile9(join21(targetRoot, "probes.json"), renderValidatedJson({
20840
+ await writeFile10(join21(targetRoot, "probes.json"), renderValidatedJson({
20586
20841
  probes: records,
20587
20842
  schemaVersion: TEST_SCHEMA,
20588
20843
  target
20589
20844
  }, `activation ${target} probes`), "utf8");
20590
20845
  for (const record of records) {
20591
20846
  const name = typeof record.name === "string" ? record.name : "probe";
20592
- await writeFile9(join21(targetRoot, `${name}.md`), renderActivationProbeMarkdown(record), "utf8");
20847
+ await writeFile10(join21(targetRoot, `${name}.md`), renderActivationProbeMarkdown(record), "utf8");
20593
20848
  }
20594
20849
  }
20595
20850
  return activationRoot;
@@ -20653,7 +20908,7 @@ async function refreshLatest(buildRoot, runPath, latestPath, report, rootPath) {
20653
20908
  source: report.source,
20654
20909
  workspacePath: relative16(rootPath, join21(latestPath, "workspace"))
20655
20910
  };
20656
- await writeFile9(join21(buildRoot, "latest.json"), renderValidatedJson(latest, relative16(rootPath, join21(buildRoot, "latest.json"))), "utf8");
20911
+ await writeFile10(join21(buildRoot, "latest.json"), renderValidatedJson(latest, relative16(rootPath, join21(buildRoot, "latest.json"))), "utf8");
20657
20912
  }
20658
20913
  function renderMarkdownReport(report) {
20659
20914
  const assertions = Array.isArray(report.assertions) ? report.assertions : [];
@@ -20699,7 +20954,7 @@ async function pathExists2(path2) {
20699
20954
  async function copyIfExists(sourcePath, targetPath) {
20700
20955
  if (!await pathExists2(sourcePath))
20701
20956
  return;
20702
- await mkdir9(dirname14(targetPath), { recursive: true });
20957
+ await mkdir10(dirname14(targetPath), { recursive: true });
20703
20958
  await cp(sourcePath, targetPath);
20704
20959
  }
20705
20960
  async function copyWorkspaceManagedFiles(rootPath, stagingWorkspacePath, workspaceLockPath, sourceDir) {
@@ -20765,8 +21020,8 @@ var USAGE = [
20765
21020
  " skillset hooks print --target <claude|codex> --agent-runtime",
20766
21021
  " skillset hooks run <post-tool-use|stop> [--root <path>]",
20767
21022
  " skillset adopt <path> [--yes|--dry-run] [--targets claude,codex] [--root <path>]",
20768
- " skillset init [path] [--yes|--dry-run] [--targets claude,codex] [--include agents,ci] [--name <name>] [--root <path>]",
20769
- " skillset create [path|--global] [--yes|--dry-run] [--targets claude,codex] [--include agents,ci] [--name <name>] [--root <path>]",
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>]",
20770
21025
  " skillset explain <path> [--json] [--scope <scope>] [--root <path>] [--source <dir>]",
20771
21026
  " skillset import <path> [--kind <skill|skills|plugin|plugins>] [--from <provider>] [--name <name>] [--root <path>] [--source <dir>]",
20772
21027
  " skillset import <claude|codex|agents> [--root <path>] [--source <dir>]"
@@ -20845,8 +21100,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
20845
21100
  });
20846
21101
  if (ciReportPath !== undefined) {
20847
21102
  const reportPath = resolve10(ciReportPath);
20848
- await mkdir10(dirname15(reportPath), { recursive: true });
20849
- await writeFile10(reportPath, renderCiReportMarkdown(report));
21103
+ await mkdir11(dirname15(reportPath), { recursive: true });
21104
+ await writeFile11(reportPath, renderCiReportMarkdown(report));
20850
21105
  }
20851
21106
  printCiReport(report);
20852
21107
  if (!report.ok)
@@ -21159,8 +21414,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
21159
21414
  console.log(` claude: ${feature2.targetSupport.claude.status}`);
21160
21415
  console.log(` codex: ${feature2.targetSupport.codex.status}`);
21161
21416
  }
21162
- for (const outcome of result3.loweringOutcomes) {
21163
- printLoweringOutcome(outcome);
21417
+ for (const outcome of result3.renderResults) {
21418
+ printRenderResult(outcome);
21164
21419
  }
21165
21420
  for (const note of result3.notes)
21166
21421
  console.log(` note: ${note}`);
@@ -21191,14 +21446,14 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
21191
21446
  console.log(` features: ${report.featureCapabilities.total} registry entries; status ${formatCountSummary(report.featureCapabilities.byFeatureStatus)}`);
21192
21447
  console.log(` feature support: claude ${formatCountSummary(report.featureCapabilities.byTargetSupport.claude)}`);
21193
21448
  console.log(` feature support: codex ${formatCountSummary(report.featureCapabilities.byTargetSupport.codex)}`);
21194
- for (const outcome of report.notableLoweringOutcomes) {
21195
- printLoweringOutcome(outcome);
21449
+ for (const outcome of report.notableRenderResults) {
21450
+ printRenderResult(outcome);
21196
21451
  }
21197
21452
  if (report.ok) {
21198
- if (report.notableLoweringOutcomes.length === 0) {
21453
+ if (report.notableRenderResults.length === 0) {
21199
21454
  console.log("skillset: doctor found no problems");
21200
21455
  } else {
21201
- console.log(`skillset: doctor found ${report.notableLoweringOutcomes.length} lowering outcome advisor${report.notableLoweringOutcomes.length === 1 ? "y" : "ies"}`);
21456
+ console.log(`skillset: doctor found ${report.notableRenderResults.length} render result advisor${report.notableRenderResults.length === 1 ? "y" : "ies"}`);
21202
21457
  }
21203
21458
  } else {
21204
21459
  const problems = [];
@@ -21208,8 +21463,8 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
21208
21463
  problems.push("generated-output drift");
21209
21464
  if (report.buildError !== undefined)
21210
21465
  problems.push("a build error");
21211
- if (report.notableLoweringOutcomes.length > 0) {
21212
- problems.push(`${report.notableLoweringOutcomes.length} lowering outcome advisor${report.notableLoweringOutcomes.length === 1 ? "y" : "ies"}`);
21466
+ if (report.notableRenderResults.length > 0) {
21467
+ problems.push(`${report.notableRenderResults.length} render result advisor${report.notableRenderResults.length === 1 ? "y" : "ies"}`);
21213
21468
  }
21214
21469
  console.log(`skillset: doctor found ${problems.join(" and ")}`);
21215
21470
  process.exitCode = 1;
@@ -21275,6 +21530,9 @@ function printChangeCheck(report) {
21275
21530
  const path2 = issue.path === undefined ? "" : `${issue.path}: `;
21276
21531
  console.log(` ${issue.severity}: ${path2}${issue.code}: ${issue.message}`);
21277
21532
  }
21533
+ for (const group of report.stackedEvidence) {
21534
+ console.log(` stacked evidence: ${sourceUnitDisplay(group.scope)} ${group.sourceHash} shared by ${group.paths.length} pending entries: ${group.paths.join(", ")}`);
21535
+ }
21278
21536
  const errors = report.issues.filter((issue) => issue.severity === "error").length;
21279
21537
  const warnings = report.issues.length - errors;
21280
21538
  if (errors === 0) {
@@ -21572,11 +21830,12 @@ function formatFeatureSupport(support) {
21572
21830
  function formatCountSummary(counts) {
21573
21831
  return Object.entries(counts).sort(([left], [right]) => left.localeCompare(right)).map(([key, count]) => `${key} ${count}`).join(", ");
21574
21832
  }
21575
- function printLoweringOutcome(outcome) {
21833
+ function printRenderResult(outcome) {
21576
21834
  const target = outcome.target ?? "workspace";
21835
+ const destination = outcome.destination === undefined ? "" : ` -> ${outcome.destination}`;
21577
21836
  const policy = outcome.policy === undefined ? "" : ` policy: ${outcome.policy}`;
21578
21837
  const reason = outcome.reason === undefined ? "" : ` reason: ${outcome.reason}`;
21579
- console.log(` lowering [${target}] ${outcome.sourceUnit}: ${outcome.featureId} ${outcome.status}${policy}${reason}`);
21838
+ console.log(` render [${target}] ${outcome.sourceUnit}: ${outcome.featureId}${destination} ${outcome.status}${policy}${reason}`);
21580
21839
  if (outcome.outputs !== undefined && outcome.outputs.length > 0) {
21581
21840
  console.log(` outputs: ${outcome.outputs.map((output) => output.path).join(", ")}`);
21582
21841
  }
@@ -22096,8 +22355,8 @@ function mergeSetupIncludes(current, value) {
22096
22355
  throw new Error("skillset: --include requires at least one value");
22097
22356
  const seen = new Set(current ?? []);
22098
22357
  for (const include of includes) {
22099
- if (include !== "agents" && include !== "ci") {
22100
- throw new Error("skillset: expected --include agents, ci, or a comma-separated combination");
22358
+ if (include !== "ci") {
22359
+ throw new Error("skillset: expected --include ci");
22101
22360
  }
22102
22361
  seen.add(include);
22103
22362
  }