@hasna/instructions 0.7.2 → 0.7.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 (41) hide show
  1. package/README.md +13 -0
  2. package/dist/chunks/{apply-wj7wh5km.js → apply-1cpkx082.js} +2 -2
  3. package/dist/chunks/{apply-ps6jjt6k.js → apply-xraar7p0.js} +2 -2
  4. package/dist/chunks/{index-pq18fdbj.js → index-16j8x10s.js} +64 -3
  5. package/dist/chunks/{index-n6nh6f5r.js → index-6qfy0542.js} +193 -15
  6. package/dist/chunks/{index-ek15201v.js → index-rvb4znxa.js} +2 -2
  7. package/dist/chunks/{index-ape24zc0.js → index-src5t3my.js} +1 -1
  8. package/dist/chunks/{index-y8410ve0.js → index-x0v4m19f.js} +1 -1
  9. package/dist/chunks/{index-18j7x3xw.js → index-ysnp8y58.js} +2 -2
  10. package/dist/chunks/{local-1c1qxzvx.js → local-66fck74w.js} +1 -1
  11. package/dist/chunks/{local-hc67bynj.js → local-jqfx3kbq.js} +1 -1
  12. package/dist/chunks/{sync-azd9t4p8.js → sync-8763n4sc.js} +3 -3
  13. package/dist/chunks/{sync-12m3vs6g.js → sync-8ca3ew84.js} +3 -3
  14. package/dist/cli/index.js +526 -554
  15. package/dist/index.d.ts +4 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +727 -587
  18. package/dist/lib/asset-plan.d.ts +4 -1
  19. package/dist/lib/asset-plan.d.ts.map +1 -1
  20. package/dist/lib/harness-discovery.d.ts +52 -0
  21. package/dist/lib/harness-discovery.d.ts.map +1 -0
  22. package/dist/lib/machine.d.ts.map +1 -1
  23. package/dist/lib/managed-skill-runtimes.d.ts +12 -28
  24. package/dist/lib/managed-skill-runtimes.d.ts.map +1 -1
  25. package/dist/lib/session-apply.d.ts +11 -0
  26. package/dist/lib/session-apply.d.ts.map +1 -1
  27. package/dist/lib/session-refresh.d.ts.map +1 -1
  28. package/dist/lib/session-render.d.ts +7 -0
  29. package/dist/lib/session-render.d.ts.map +1 -1
  30. package/dist/mcp/index.js +7 -7
  31. package/dist/sdk/index.d.ts +2 -0
  32. package/dist/sdk/index.d.ts.map +1 -1
  33. package/dist/sdk/index.js +153 -0
  34. package/dist/sdk/v1.generated.d.ts +6 -0
  35. package/dist/sdk/v1.generated.d.ts.map +1 -1
  36. package/dist/server/index.js +77 -0
  37. package/dist/server/openapi.d.ts +27 -0
  38. package/dist/server/openapi.d.ts.map +1 -1
  39. package/dist/types/index.d.ts +8 -0
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/package.json +1 -1
package/README.md CHANGED
@@ -67,6 +67,19 @@ instructions package-manager-scan --fail-on-findings .
67
67
  instructions package-manager-scan --home --fail-on-findings .
68
68
  ```
69
69
 
70
+ Skills are managed through the Skills CLI. Profile application and bootstrap do
71
+ not inspect, install or repair native Inbox skill payloads, and do not send
72
+ Conversations heartbeats. Their legacy `--from` and `--delivery-verified` flags
73
+ remain accepted for compatibility but perform no verification.
74
+
75
+ `instructions managed-skills status` and `instructions managed-skills apply`
76
+ are deprecated, read-only migration reports. They return a failure when legacy
77
+ Inbox paths remain and preserve those paths, including symlinks. Use the Skills
78
+ CLI to review `skills migrate native`, then sync and load the selected skills.
79
+ An empty legacy inventory does not verify hosted skill selection or runtime
80
+ delivery. The exported inspection/reconciliation helpers behave the same way;
81
+ an explicit legacy `assetPath` no longer enables native payload writes.
82
+
70
83
  Collection commands are compact by default to keep agent terminals and context
71
84
  small. Human output is capped at 20 rows unless you pass `--limit`; use
72
85
  `--cursor` to continue from the next page. Detail is explicit:
@@ -8,8 +8,8 @@ import {
8
8
  getConfigHome,
9
9
  normalizeTargetPath,
10
10
  previewConfigs
11
- } from "./index-y8410ve0.js";
12
- import"./index-n6nh6f5r.js";
11
+ } from "./index-x0v4m19f.js";
12
+ import"./index-6qfy0542.js";
13
13
  import"./index-preyvj8n.js";
14
14
  import"./index-fpeyzn3n.js";
15
15
  import"./index-bsan4c16.js";
@@ -8,8 +8,8 @@ import {
8
8
  getConfigHome,
9
9
  normalizeTargetPath,
10
10
  previewConfigs
11
- } from "./index-ape24zc0.js";
12
- import"./index-pq18fdbj.js";
11
+ } from "./index-src5t3my.js";
12
+ import"./index-16j8x10s.js";
13
13
  import"./index-35z65jsa.js";
14
14
  import"./index-27az1qb1.js";
15
15
  import"./index-nnwp92tk.js";
@@ -373,6 +373,7 @@ function assetCapability(provider, surface, kind, support, strategies, note, pro
373
373
  var ASSET_CAPABILITY_DESCRIPTORS = Object.freeze([
374
374
  assetCapability("claude", "code", "skill", "supported", ["emit-file"], "Claude Code project or profile skill files."),
375
375
  assetCapability("claude", "code", "workflow", "supported", ["emit-file"], "Claude Code command and workflow files."),
376
+ assetCapability("claude", "code", "custom-agent", "supported", ["emit-file"], "Claude Code Markdown subagents with native frontmatter in agents/.", ">=2.1.276 <3.0.0"),
376
377
  assetCapability("claude", "code", "hook", "supported", ["emit-file"], "Claude Code hook configuration fragments."),
377
378
  assetCapability("claude", "code", "plugin", "conditional", ["install-marketplace"], "Claude marketplace installation requires an explicit installer."),
378
379
  assetCapability("codex", "cli", "skill", "supported", ["emit-file"], "Codex skill bundle files."),
@@ -383,6 +384,7 @@ var ASSET_CAPABILITY_DESCRIPTORS = Object.freeze([
383
384
  assetCapability("opencode", "cli", "workflow", "supported", ["emit-file"], "OpenCode command/workflow files."),
384
385
  assetCapability("opencode", "cli", "plugin", "supported", ["emit-file"], "OpenCode local plugin modules."),
385
386
  assetCapability("opencode", "cli", "custom-agent", "supported", ["emit-file"], "OpenCode custom agent files."),
387
+ assetCapability("sumi", "cli", "custom-agent", "supported", ["emit-file"], "Sumi Markdown agent definitions in its explicit resolved config or project directory.", ">=0.2.22 <0.3.0"),
386
388
  assetCapability("codewith", "cli", "skill", "supported", ["emit-file"], "Codewith skill bundle files."),
387
389
  assetCapability("codewith", "cli", "plugin", "conditional", ["install-local", "install-marketplace"], "Codewith plugin installation requires an explicit installer."),
388
390
  assetCapability("aicopilot", "cli", "skill", "supported", ["emit-file"], "AICopilot discovered skill files."),
@@ -465,6 +467,10 @@ function normalizeProfileAssetBinding(value) {
465
467
  const rollback = record["rollback"];
466
468
  if (!ASSET_ROLLBACK_POLICIES.includes(rollback))
467
469
  throw new Error(`Invalid asset rollback policy: ${String(rollback)}`);
470
+ const nativeAgent = record["nativeAgent"] === undefined ? undefined : normalizeNativeAgentMetadata(record["nativeAgent"]);
471
+ if (nativeAgent && (kind !== "custom-agent" || strategy !== "emit-file" || !["claude", "sumi", "opencode"].includes(provider))) {
472
+ throw new Error("nativeAgent metadata requires a supported emitted custom-agent definition.");
473
+ }
468
474
  return {
469
475
  schema: PROFILE_ASSET_BINDING_SCHEMA,
470
476
  assetKey,
@@ -484,10 +490,65 @@ function normalizeProfileAssetBinding(value) {
484
490
  root,
485
491
  relativePath: nonEmptyString(destinationRecord["relativePath"], "destination.relativePath")
486
492
  },
493
+ ...nativeAgent ? { nativeAgent } : {},
487
494
  uninstall,
488
495
  rollback
489
496
  };
490
497
  }
498
+ function normalizeNativeAgentMetadata(value) {
499
+ const record = objectRecord(value, "nativeAgent");
500
+ if (Object.keys(record).some((key) => !["name", "description", "frontmatter"].includes(key)))
501
+ throw new Error("Unknown nativeAgent metadata field.");
502
+ const name = nonEmptyString(record["name"], "nativeAgent.name");
503
+ const description = nonEmptyString(record["description"], "nativeAgent.description");
504
+ if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(name) || name.length > 128)
505
+ throw new Error("Invalid nativeAgent.name.");
506
+ if (description.length > 4096 || /[\r\n\0]/.test(description))
507
+ throw new Error("Invalid nativeAgent.description.");
508
+ if (record["frontmatter"] === undefined)
509
+ return { name, description };
510
+ const frontmatter = record["frontmatter"];
511
+ if (typeof frontmatter !== "string" || frontmatter.length > 16384 || frontmatter.includes("\x00"))
512
+ throw new Error("Invalid nativeAgent.frontmatter.");
513
+ const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n$/.exec(frontmatter);
514
+ if (!match)
515
+ throw new Error("nativeAgent.frontmatter requires one complete newline-terminated YAML header.");
516
+ const scalar = (raw) => {
517
+ if (raw.startsWith('"')) {
518
+ try {
519
+ const parsed = JSON.parse(raw);
520
+ return typeof parsed === "string" ? parsed : undefined;
521
+ } catch {
522
+ return;
523
+ }
524
+ }
525
+ if (!/^[A-Za-z0-9][A-Za-z0-9 _.,:;()/?@+-]*$/.test(raw) || /:(?:\s|$)/.test(raw))
526
+ return;
527
+ if (/^(?:true|yes|on|y)$/i.test(raw))
528
+ return true;
529
+ if (/^(?:false|no|off|n)$/i.test(raw))
530
+ return false;
531
+ if (/^null$/i.test(raw))
532
+ return null;
533
+ if (/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/.test(raw))
534
+ return Number(raw);
535
+ if (/^[0-9]/.test(raw))
536
+ return;
537
+ return raw;
538
+ };
539
+ const fields = new Map;
540
+ for (const line of match[1].split(/\r?\n/)) {
541
+ if (!line.trim() || line.startsWith("#"))
542
+ continue;
543
+ const field = /^([A-Za-z][A-Za-z0-9_-]*):[ \t]+(.+)$/.exec(line);
544
+ if (!field || fields.has(field[1]) || scalar(field[2]) === undefined)
545
+ throw new Error("nativeAgent.frontmatter requires unambiguous, unique flat scalar fields.");
546
+ fields.set(field[1], scalar(field[2]));
547
+ }
548
+ if (fields.get("name") !== name || fields.get("description") !== description)
549
+ throw new Error("nativeAgent.frontmatter name and description must match explicit metadata.");
550
+ return { name, description, frontmatter };
551
+ }
491
552
  function parseJson(value) {
492
553
  try {
493
554
  return JSON.parse(value);
@@ -2123,7 +2184,7 @@ function isNotFoundHttpError2(err) {
2123
2184
  var localStoreModulePromise = null;
2124
2185
  function localStoreModule() {
2125
2186
  if (!localStoreModulePromise)
2126
- localStoreModulePromise = import("./local-1c1qxzvx.js");
2187
+ localStoreModulePromise = import("./local-66fck74w.js");
2127
2188
  return localStoreModulePromise;
2128
2189
  }
2129
2190
 
@@ -7344,7 +7405,7 @@ function detectMachineContext(overrides = {}) {
7344
7405
  created_at: "",
7345
7406
  os_family: osFamily,
7346
7407
  home_dir: homeDir4,
7347
- workspace_root: overrides.workspace_root ?? join5(homeDir4, osFamily === "macos" ? "Workspace" : "workspace"),
7408
+ workspace_root: overrides.workspace_root ?? "",
7348
7409
  bun_bin_dir: bunBinDir,
7349
7410
  bun_path: overrides.bun_path ?? defaultBunPath,
7350
7411
  path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join5("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
@@ -7357,7 +7418,7 @@ function machineContextToVariables(machine) {
7357
7418
  OS_FAMILY: machine.os_family,
7358
7419
  ARCH: machine.arch ?? "",
7359
7420
  HOME_DIR: machine.home_dir,
7360
- WORKSPACE_ROOT: machine.workspace_root,
7421
+ ...machine.workspace_root ? { WORKSPACE_ROOT: machine.workspace_root } : {},
7361
7422
  BUN_BIN_DIR: machine.bun_bin_dir,
7362
7423
  BUN_PATH: machine.bun_path,
7363
7424
  PATH_PREFIX: machine.path_prefix
@@ -7510,6 +7510,7 @@ function assetCapability(provider, surface, kind, support, strategies, note, pro
7510
7510
  var ASSET_CAPABILITY_DESCRIPTORS = Object.freeze([
7511
7511
  assetCapability("claude", "code", "skill", "supported", ["emit-file"], "Claude Code project or profile skill files."),
7512
7512
  assetCapability("claude", "code", "workflow", "supported", ["emit-file"], "Claude Code command and workflow files."),
7513
+ assetCapability("claude", "code", "custom-agent", "supported", ["emit-file"], "Claude Code Markdown subagents with native frontmatter in agents/.", ">=2.1.276 <3.0.0"),
7513
7514
  assetCapability("claude", "code", "hook", "supported", ["emit-file"], "Claude Code hook configuration fragments."),
7514
7515
  assetCapability("claude", "code", "plugin", "conditional", ["install-marketplace"], "Claude marketplace installation requires an explicit installer."),
7515
7516
  assetCapability("codex", "cli", "skill", "supported", ["emit-file"], "Codex skill bundle files."),
@@ -7520,6 +7521,7 @@ var ASSET_CAPABILITY_DESCRIPTORS = Object.freeze([
7520
7521
  assetCapability("opencode", "cli", "workflow", "supported", ["emit-file"], "OpenCode command/workflow files."),
7521
7522
  assetCapability("opencode", "cli", "plugin", "supported", ["emit-file"], "OpenCode local plugin modules."),
7522
7523
  assetCapability("opencode", "cli", "custom-agent", "supported", ["emit-file"], "OpenCode custom agent files."),
7524
+ assetCapability("sumi", "cli", "custom-agent", "supported", ["emit-file"], "Sumi Markdown agent definitions in its explicit resolved config or project directory.", ">=0.2.22 <0.3.0"),
7523
7525
  assetCapability("codewith", "cli", "skill", "supported", ["emit-file"], "Codewith skill bundle files."),
7524
7526
  assetCapability("codewith", "cli", "plugin", "conditional", ["install-local", "install-marketplace"], "Codewith plugin installation requires an explicit installer."),
7525
7527
  assetCapability("aicopilot", "cli", "skill", "supported", ["emit-file"], "AICopilot discovered skill files."),
@@ -7623,6 +7625,10 @@ function normalizeProfileAssetBinding(value) {
7623
7625
  const rollback = record["rollback"];
7624
7626
  if (!ASSET_ROLLBACK_POLICIES.includes(rollback))
7625
7627
  throw new Error(`Invalid asset rollback policy: ${String(rollback)}`);
7628
+ const nativeAgent = record["nativeAgent"] === undefined ? undefined : normalizeNativeAgentMetadata(record["nativeAgent"]);
7629
+ if (nativeAgent && (kind !== "custom-agent" || strategy !== "emit-file" || !["claude", "sumi", "opencode"].includes(provider))) {
7630
+ throw new Error("nativeAgent metadata requires a supported emitted custom-agent definition.");
7631
+ }
7626
7632
  return {
7627
7633
  schema: PROFILE_ASSET_BINDING_SCHEMA,
7628
7634
  assetKey,
@@ -7642,6 +7648,7 @@ function normalizeProfileAssetBinding(value) {
7642
7648
  root,
7643
7649
  relativePath: nonEmptyString(destinationRecord["relativePath"], "destination.relativePath")
7644
7650
  },
7651
+ ...nativeAgent ? { nativeAgent } : {},
7645
7652
  uninstall,
7646
7653
  rollback
7647
7654
  };
@@ -7717,6 +7724,7 @@ function compileAssetPlan(input) {
7717
7724
  allowed: binding.source.allowed
7718
7725
  },
7719
7726
  destination: binding.destination,
7727
+ ...binding.nativeAgent ? { nativeAgent: binding.nativeAgent } : {},
7720
7728
  support,
7721
7729
  action,
7722
7730
  mutationMode: input.mode,
@@ -7781,6 +7789,18 @@ function validateAssetSourceAndDestination(bundle, binding, diagnostics) {
7781
7789
  pathSafe = false;
7782
7790
  diagnostics.push(diagnostic("error", "ASSET_DESTINATION_UNSAFE", binding.assetKey, error.message));
7783
7791
  }
7792
+ if (pathSafe && binding.kind === "custom-agent" && binding.destination.strategy === "emit-file" && (binding.selector.provider === "claude" || binding.selector.provider === "sumi" || binding.nativeAgent) && (binding.destination.root !== "target-home" || !/^agents\/[A-Za-z0-9][A-Za-z0-9_-]*\.md$/.test(safeRelativePath(binding.destination.relativePath)))) {
7793
+ pathSafe = false;
7794
+ diagnostics.push(diagnostic("error", "ASSET_CUSTOM_AGENT_DESTINATION_UNSUPPORTED", binding.assetKey, "Native custom-agent definitions require agents/<name>.md beneath an explicit target-home."));
7795
+ }
7796
+ if (binding.nativeAgent) {
7797
+ if (posix.basename(binding.destination.relativePath, ".md") !== binding.nativeAgent.name) {
7798
+ diagnostics.push(diagnostic("error", "ASSET_NATIVE_AGENT_NAME_MISMATCH", binding.assetKey, "Native role name must match its destination filename."));
7799
+ }
7800
+ if (/^\uFEFF?---[ \t]*\r?\n/.test(bundle.content)) {
7801
+ diagnostics.push(diagnostic("error", "ASSET_NATIVE_AGENT_DOUBLE_HEADER", binding.assetKey, "Canonical role prose must not already contain frontmatter when nativeAgent metadata is supplied."));
7802
+ }
7803
+ }
7784
7804
  const expectedLocator = bundle.locator;
7785
7805
  if (!binding.source.immutable || binding.source.locator !== expectedLocator) {
7786
7806
  diagnostics.push(diagnostic("error", "ASSET_SOURCE_MUTABLE_OR_UNPINNED", binding.assetKey, `Asset source must be pinned to ${expectedLocator}.`));
@@ -7836,6 +7856,72 @@ function safeRelativePath(value) {
7836
7856
  }
7837
7857
  return normalized;
7838
7858
  }
7859
+ function normalizeNativeAgentMetadata(value) {
7860
+ const record = objectRecord(value, "nativeAgent");
7861
+ if (Object.keys(record).some((key) => !["name", "description", "frontmatter"].includes(key)))
7862
+ throw new Error("Unknown nativeAgent metadata field.");
7863
+ const name = nonEmptyString(record["name"], "nativeAgent.name");
7864
+ const description = nonEmptyString(record["description"], "nativeAgent.description");
7865
+ if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(name) || name.length > 128)
7866
+ throw new Error("Invalid nativeAgent.name.");
7867
+ if (description.length > 4096 || /[\r\n\0]/.test(description))
7868
+ throw new Error("Invalid nativeAgent.description.");
7869
+ if (record["frontmatter"] === undefined)
7870
+ return { name, description };
7871
+ const frontmatter = record["frontmatter"];
7872
+ if (typeof frontmatter !== "string" || frontmatter.length > 16384 || frontmatter.includes("\x00"))
7873
+ throw new Error("Invalid nativeAgent.frontmatter.");
7874
+ const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n$/.exec(frontmatter);
7875
+ if (!match)
7876
+ throw new Error("nativeAgent.frontmatter requires one complete newline-terminated YAML header.");
7877
+ const scalar = (raw) => {
7878
+ if (raw.startsWith('"')) {
7879
+ try {
7880
+ const parsed = JSON.parse(raw);
7881
+ return typeof parsed === "string" ? parsed : undefined;
7882
+ } catch {
7883
+ return;
7884
+ }
7885
+ }
7886
+ if (!/^[A-Za-z0-9][A-Za-z0-9 _.,:;()/?@+-]*$/.test(raw) || /:(?:\s|$)/.test(raw))
7887
+ return;
7888
+ if (/^(?:true|yes|on|y)$/i.test(raw))
7889
+ return true;
7890
+ if (/^(?:false|no|off|n)$/i.test(raw))
7891
+ return false;
7892
+ if (/^null$/i.test(raw))
7893
+ return null;
7894
+ if (/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/.test(raw))
7895
+ return Number(raw);
7896
+ if (/^[0-9]/.test(raw))
7897
+ return;
7898
+ return raw;
7899
+ };
7900
+ const fields = new Map;
7901
+ for (const line of match[1].split(/\r?\n/)) {
7902
+ if (!line.trim() || line.startsWith("#"))
7903
+ continue;
7904
+ const field = /^([A-Za-z][A-Za-z0-9_-]*):[ \t]+(.+)$/.exec(line);
7905
+ if (!field || fields.has(field[1]) || scalar(field[2]) === undefined)
7906
+ throw new Error("nativeAgent.frontmatter requires unambiguous, unique flat scalar fields.");
7907
+ fields.set(field[1], scalar(field[2]));
7908
+ }
7909
+ if (fields.get("name") !== name || fields.get("description") !== description)
7910
+ throw new Error("nativeAgent.frontmatter name and description must match explicit metadata.");
7911
+ return { name, description, frontmatter };
7912
+ }
7913
+ function renderNativeAgentContent(content, metadata) {
7914
+ if (!metadata)
7915
+ return content;
7916
+ const value = normalizeNativeAgentMetadata(metadata);
7917
+ if (/^\uFEFF?---[ \t]*\r?\n/.test(content))
7918
+ throw new Error("Canonical role prose already contains frontmatter.");
7919
+ return (value.frontmatter ?? `---
7920
+ name: ${JSON.stringify(value.name)}
7921
+ description: ${JSON.stringify(value.description)}
7922
+ ---
7923
+ `) + content;
7924
+ }
7839
7925
  function diagnostic(severity, code, assetKey, message) {
7840
7926
  return { severity, code, assetKey, message };
7841
7927
  }
@@ -9066,7 +9152,7 @@ function buildCursorRuleFiles(targetHome, adapter, sources) {
9066
9152
  return [sourceFile, ...ruleFiles];
9067
9153
  });
9068
9154
  }
9069
- function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfig) {
9155
+ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfig, projectRoot) {
9070
9156
  const surface = adapter.providerSurface ?? "legacy-dual";
9071
9157
  const fragments = sources.flatMap((source, index) => [
9072
9158
  makeFile(targetHome, fragmentPath(adapter, index, source), "fragment", sectionForSource(source), [source.id]),
@@ -9086,13 +9172,13 @@ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfi
9086
9172
  ]);
9087
9173
  const existingConfigPath = joinTarget(targetHome, adapter.configFile);
9088
9174
  const selectedConfig = existsSync4(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
9089
- const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir));
9175
+ const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir, targetHome, projectRoot));
9090
9176
  const config = {
9091
9177
  ...selectedConfig,
9092
9178
  $schema: typeof selectedConfig["$schema"] === "string" ? selectedConfig["$schema"] : "https://opencode.ai/config.json",
9093
9179
  instructions: [
9094
9180
  ...preservedInstructions,
9095
- ...fragments.map((file) => file.relativePath)
9181
+ ...fragments.map((file) => file.path)
9096
9182
  ]
9097
9183
  };
9098
9184
  const configSourceIds = [
@@ -9135,9 +9221,99 @@ function normalizeOpenCodeInstructions(value) {
9135
9221
  }
9136
9222
  return value;
9137
9223
  }
9138
- function pathIsManagedOpenCodeInstruction(path, managedDir) {
9139
- const normalized = posix2.normalize(path.replaceAll("\\", "/")).replace(/^\.\//, "");
9140
- return normalized === managedDir || normalized.startsWith(`${managedDir}/`);
9224
+ function pathIsManagedOpenCodeInstruction(reference, managedDir, targetHome, projectRoot) {
9225
+ const normalizedManagedDir = posix2.normalize(managedDir.replaceAll("\\", "/"));
9226
+ const candidates = canonicalOpenCodeInstructionPaths(reference, targetHome, projectRoot);
9227
+ return candidates.some((candidate) => {
9228
+ const path = candidate.caseInsensitive ? candidate.path.toLowerCase() : candidate.path;
9229
+ const namespace = candidate.caseInsensitive ? normalizedManagedDir.toLowerCase() : normalizedManagedDir;
9230
+ return path === namespace || path.endsWith(`/${namespace}`) || path.includes(`/${namespace}/`);
9231
+ });
9232
+ }
9233
+ function canonicalOpenCodeInstructionPaths(reference, targetHome, projectRoot) {
9234
+ const decodedReference = decodeOpenCodePathEscapes(reference);
9235
+ const portable = decodedReference.replaceAll("\\", "/");
9236
+ if (portable.includes("\x00")) {
9237
+ throw new Error("OpenCode config instruction references cannot contain NUL bytes.");
9238
+ }
9239
+ if (/^[A-Za-z]:(?!\/)/.test(portable)) {
9240
+ throw new Error("OpenCode config instruction references cannot use Win32 drive-relative paths.");
9241
+ }
9242
+ const windowsAbsolute = /^[A-Za-z]:\//.test(portable);
9243
+ const uncAbsolute = portable.startsWith("//");
9244
+ const windowsRootRelative = /^\\(?![\\/])/.test(decodedReference);
9245
+ const uriScheme = windowsAbsolute || uncAbsolute || windowsRootRelative ? null : /^([A-Za-z][A-Za-z0-9+.-]*):/.exec(portable)?.[1]?.toLowerCase();
9246
+ if (uriScheme && uriScheme !== "file")
9247
+ return [];
9248
+ if (uriScheme === "file") {
9249
+ const fileReference = reference.replaceAll("\\", "/");
9250
+ if (!/^file:\/\//i.test(fileReference)) {
9251
+ throw new Error("OpenCode config contains an invalid file URL instruction reference.");
9252
+ }
9253
+ let url;
9254
+ try {
9255
+ url = new URL(fileReference);
9256
+ } catch {
9257
+ throw new Error("OpenCode config contains an invalid file URL instruction reference.");
9258
+ }
9259
+ if (url.protocol !== "file:" || url.username || url.password || url.port || url.search || url.hash) {
9260
+ throw new Error("OpenCode config contains an invalid file URL instruction reference.");
9261
+ }
9262
+ const pathname = decodeOpenCodePathEscapes(url.pathname).replaceAll("\\", "/");
9263
+ if (pathname.includes("\x00")) {
9264
+ throw new Error("OpenCode config instruction references cannot contain NUL bytes.");
9265
+ }
9266
+ if (/^\/[A-Za-z]:(?!\/)/.test(pathname)) {
9267
+ throw new Error("OpenCode config instruction references cannot use Win32 drive-relative paths.");
9268
+ }
9269
+ const host = url.hostname && url.hostname !== "localhost" ? `//${url.hostname}` : "";
9270
+ return [{
9271
+ path: normalizePortableOpenCodePath(`${host}${pathname}`, true),
9272
+ caseInsensitive: true
9273
+ }];
9274
+ }
9275
+ if (posix2.isAbsolute(portable) || windowsAbsolute || uncAbsolute || windowsRootRelative) {
9276
+ const windowsPathSemantics = windowsAbsolute || uncAbsolute || windowsRootRelative;
9277
+ return [{
9278
+ path: normalizePortableOpenCodePath(portable, windowsPathSemantics),
9279
+ caseInsensitive: windowsPathSemantics
9280
+ }];
9281
+ }
9282
+ const roots = [
9283
+ ...projectRoot ? [resolveSessionPath(projectRoot)] : [],
9284
+ resolveSessionPath(targetHome)
9285
+ ];
9286
+ const candidates = new Map;
9287
+ for (const root of roots) {
9288
+ const portableRoot = root.replaceAll("\\", "/");
9289
+ const caseInsensitive = /^[A-Za-z]:\//.test(portableRoot) || portableRoot.startsWith("//");
9290
+ const path = normalizePortableOpenCodePath(posix2.join(portableRoot, portable));
9291
+ candidates.set(`${caseInsensitive ? "i" : "s"}:${path}`, { path, caseInsensitive });
9292
+ }
9293
+ return [...candidates.values()];
9294
+ }
9295
+ function decodeOpenCodePathEscapes(value) {
9296
+ return value.replace(/(?:%[a-fA-F0-9]{2})+/g, (encoded) => {
9297
+ try {
9298
+ return decodeURIComponent(encoded);
9299
+ } catch {
9300
+ return encoded;
9301
+ }
9302
+ });
9303
+ }
9304
+ function normalizePortableOpenCodePath(value, windowsPathSemantics = false) {
9305
+ const portable = value.replaceAll("\\", "/");
9306
+ const componentNormalized = windowsPathSemantics ? portable.split("/").map(normalizeWin32PathComponent).join("/") : portable;
9307
+ const normalized = posix2.normalize(componentNormalized);
9308
+ return normalized.startsWith("//") ? `/${normalized.replace(/^\/+/u, "")}` : normalized;
9309
+ }
9310
+ function normalizeWin32PathComponent(component) {
9311
+ if (!component || /^[A-Za-z]:$/.test(component))
9312
+ return component;
9313
+ const withoutTrailingSpaces = component.replace(/ +$/u, "");
9314
+ if (withoutTrailingSpaces === "." || withoutTrailingSpaces === "..")
9315
+ return withoutTrailingSpaces;
9316
+ return component.replace(/[ .]+$/u, "");
9141
9317
  }
9142
9318
  function buildAntigravityRuleFiles(targetHome, adapter, sources) {
9143
9319
  return sources.flatMap((source, index) => {
@@ -9191,7 +9367,7 @@ function makeAntigravityRuleFile(targetHome, relativePath, content, sourceIds) {
9191
9367
  }
9192
9368
  return file;
9193
9369
  }
9194
- function buildFiles(targetHome, adapter, profile, sources, providerConfig, providerVersion) {
9370
+ function buildFiles(targetHome, adapter, profile, sources, providerConfig, providerVersion, projectRoot) {
9195
9371
  switch (adapter.mode) {
9196
9372
  case "native-imports":
9197
9373
  return buildNativeImportFiles(targetHome, adapter, profile, sources, providerVersion);
@@ -9200,7 +9376,7 @@ function buildFiles(targetHome, adapter, profile, sources, providerConfig, provi
9200
9376
  case "cursor-mdc":
9201
9377
  return buildCursorRuleFiles(targetHome, adapter, sources);
9202
9378
  case "opencode-instructions":
9203
- return buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfig);
9379
+ return buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfig, projectRoot);
9204
9380
  case "antigravity-rules":
9205
9381
  return buildAntigravityRuleFiles(targetHome, adapter, sources);
9206
9382
  case "provider-rules":
@@ -9229,12 +9405,13 @@ function buildAssetFiles(input, targetHome, blocked) {
9229
9405
  if (!relativePath || relativePath === ".." || relativePath.startsWith("../") || isAbsolute3(relativePath)) {
9230
9406
  throw new Error(`Asset ${item.assetKey} is outside the session snapshot root; use a project-scoped session plan for atomic application.`);
9231
9407
  }
9408
+ const renderedContent = renderNativeAgentContent(content, item.nativeAgent);
9232
9409
  return {
9233
9410
  path,
9234
9411
  relativePath: assertSafeRelativePath(relativePath),
9235
9412
  role: "asset",
9236
- content,
9237
- sha256: sha2565(content),
9413
+ content: renderedContent,
9414
+ sha256: sha2565(renderedContent),
9238
9415
  sourceIds: [item.sourceConfigId, item.assetId]
9239
9416
  };
9240
9417
  });
@@ -9413,7 +9590,7 @@ function resolveSessionTargetOwnership(input, target) {
9413
9590
  tool: input.tool,
9414
9591
  profile: input.profile,
9415
9592
  targetHome: target.targetHome,
9416
- projectRoot: null,
9593
+ projectRoot: input.tool === "opencode" && input.projectRoot ? resolveSessionPath(input.projectRoot) : null,
9417
9594
  ownedBy: "open-configs",
9418
9595
  canonicalOwner: "instructions",
9419
9596
  writer: {
@@ -9474,7 +9651,7 @@ function planSessionRender(input) {
9474
9651
  if (input.providerConfig && input.tool !== "opencode") {
9475
9652
  throw new Error("Provider base config is supported only for OpenCode session renders.");
9476
9653
  }
9477
- const baseFiles = blocked ? [] : buildFiles(targetHome, adapter, input.profile, orderedSources, input.providerConfig, input.provider_version);
9654
+ const baseFiles = blocked ? [] : buildFiles(targetHome, adapter, input.profile, orderedSources, input.providerConfig, input.provider_version, input.projectRoot);
9478
9655
  const projectContext = blocked ? null : composeProjectContextSessionRender({
9479
9656
  tool: input.tool,
9480
9657
  adapter_mode: adapter.mode,
@@ -9575,6 +9752,7 @@ function planSessionRender(input) {
9575
9752
  mutationMode: item.mutationMode,
9576
9753
  destination: item.destination,
9577
9754
  digest: item.source.digest,
9755
+ ...item.nativeAgent ? { nativeAgent: item.nativeAgent } : {},
9578
9756
  exactOnceKey: item.exactOnceKey
9579
9757
  }))
9580
9758
  }
@@ -11911,7 +12089,7 @@ function formatCliError(err, env = process.env) {
11911
12089
  var localStoreModulePromise = null;
11912
12090
  function localStoreModule() {
11913
12091
  if (!localStoreModulePromise)
11914
- localStoreModulePromise = import("./local-hc67bynj.js");
12092
+ localStoreModulePromise = import("./local-jqfx3kbq.js");
11915
12093
  return localStoreModulePromise;
11916
12094
  }
11917
12095
 
@@ -12723,7 +12901,7 @@ function detectMachineContext(overrides = {}) {
12723
12901
  created_at: "",
12724
12902
  os_family: osFamily,
12725
12903
  home_dir: homeDir4,
12726
- workspace_root: overrides.workspace_root ?? join7(homeDir4, osFamily === "macos" ? "Workspace" : "workspace"),
12904
+ workspace_root: overrides.workspace_root ?? "",
12727
12905
  bun_bin_dir: bunBinDir,
12728
12906
  bun_path: overrides.bun_path ?? defaultBunPath,
12729
12907
  path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join7("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
@@ -12736,7 +12914,7 @@ function machineContextToVariables(machine) {
12736
12914
  OS_FAMILY: machine.os_family,
12737
12915
  ARCH: machine.arch ?? "",
12738
12916
  HOME_DIR: machine.home_dir,
12739
- WORKSPACE_ROOT: machine.workspace_root,
12917
+ ...machine.workspace_root ? { WORKSPACE_ROOT: machine.workspace_root } : {},
12740
12918
  BUN_BIN_DIR: machine.bun_bin_dir,
12741
12919
  BUN_PATH: machine.bun_path,
12742
12920
  PATH_PREFIX: machine.path_prefix
@@ -5,7 +5,7 @@ import {
5
5
  expandPath,
6
6
  getConfigHome,
7
7
  normalizeTargetPath
8
- } from "./index-ape24zc0.js";
8
+ } from "./index-src5t3my.js";
9
9
  import {
10
10
  applyTransform,
11
11
  detectMachineContext,
@@ -13,7 +13,7 @@ import {
13
13
  resolveConfigStore,
14
14
  retiredOrUnsupportedAgentReason,
15
15
  templateizeMachineContent
16
- } from "./index-pq18fdbj.js";
16
+ } from "./index-16j8x10s.js";
17
17
  import {
18
18
  isSecretVarName,
19
19
  redactContent,
@@ -15,7 +15,7 @@ import {
15
15
  resolveConfigStore,
16
16
  resolveProfileVariables,
17
17
  stampCursorGlobalAuthorityMarker
18
- } from "./index-pq18fdbj.js";
18
+ } from "./index-16j8x10s.js";
19
19
  import {
20
20
  isSecretVarName,
21
21
  redactFormatForTarget,
@@ -18,7 +18,7 @@ import {
18
18
  resolveProfileVariables,
19
19
  scanSecrets,
20
20
  stampCursorGlobalAuthorityMarker
21
- } from "./index-n6nh6f5r.js";
21
+ } from "./index-6qfy0542.js";
22
22
  import {
23
23
  ConfigApplyError,
24
24
  parseTemplateVars
@@ -5,7 +5,7 @@ import {
5
5
  expandPath,
6
6
  getConfigHome,
7
7
  normalizeTargetPath
8
- } from "./index-y8410ve0.js";
8
+ } from "./index-x0v4m19f.js";
9
9
  import {
10
10
  applyTransform,
11
11
  detectMachineContext,
@@ -16,7 +16,7 @@ import {
16
16
  resolveConfigStore,
17
17
  retiredOrUnsupportedAgentReason,
18
18
  templateizeMachineContent
19
- } from "./index-n6nh6f5r.js";
19
+ } from "./index-6qfy0542.js";
20
20
 
21
21
  // src/lib/sync.ts
22
22
  import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
@@ -14,7 +14,7 @@ import {
14
14
  normalizeOsFamily,
15
15
  normalizeProfileAssetBinding,
16
16
  normalizeProfileConfigBinding
17
- } from "./index-pq18fdbj.js";
17
+ } from "./index-16j8x10s.js";
18
18
  import"./index-35z65jsa.js";
19
19
  import {
20
20
  ConfigNotFoundError,
@@ -7,7 +7,7 @@ import {
7
7
  normalizeOsFamily,
8
8
  normalizeProfileAssetBinding,
9
9
  normalizeProfileConfigBinding
10
- } from "./index-n6nh6f5r.js";
10
+ } from "./index-6qfy0542.js";
11
11
  import {
12
12
  ConfigNotFoundError,
13
13
  ConfigVersionConflictError,
@@ -12,9 +12,9 @@ import {
12
12
  syncProject,
13
13
  syncToDir,
14
14
  syncToDisk
15
- } from "./index-18j7x3xw.js";
16
- import"./index-y8410ve0.js";
17
- import"./index-n6nh6f5r.js";
15
+ } from "./index-ysnp8y58.js";
16
+ import"./index-x0v4m19f.js";
17
+ import"./index-6qfy0542.js";
18
18
  import"./index-preyvj8n.js";
19
19
  import"./index-fpeyzn3n.js";
20
20
  import"./index-bsan4c16.js";
@@ -12,9 +12,9 @@ import {
12
12
  syncProject,
13
13
  syncToDir,
14
14
  syncToDisk
15
- } from "./index-ek15201v.js";
16
- import"./index-ape24zc0.js";
17
- import"./index-pq18fdbj.js";
15
+ } from "./index-rvb4znxa.js";
16
+ import"./index-src5t3my.js";
17
+ import"./index-16j8x10s.js";
18
18
  import"./index-35z65jsa.js";
19
19
  import"./index-27az1qb1.js";
20
20
  import"./index-nnwp92tk.js";