@fro.bot/systematic 3.15.0 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,21 +1,25 @@
1
1
  // @bun
2
2
  import {
3
+ parseFrontmatter,
4
+ string,
5
+ array,
6
+ object,
7
+ record,
8
+ _enum,
3
9
  AgentOverlaySchema,
4
10
  CategoryOverlaySchema,
5
- __require,
6
- discoverSkills,
7
- exports_external,
8
- extractAgentFrontmatter,
9
- extractCommandFrontmatter,
10
- findAgentsInDir,
11
- findCommandsInDir,
12
- findSkillsInDir,
13
- isDiscoverableMarkdown,
14
11
  isRecord,
12
+ resolveRouting,
15
13
  loadConfig,
16
14
  loadConfigWithSources,
17
- parseFrontmatter
18
- } from "./index-0stf3ag0.js";
15
+ isDiscoverableMarkdown,
16
+ findAgentsInDir,
17
+ extractAgentFrontmatter,
18
+ findCommandsInDir,
19
+ extractCommandFrontmatter,
20
+ findSkillsInDir,
21
+ discoverSkills
22
+ } from "./index-ae6mhwth.js";
19
23
 
20
24
  // src/index.ts
21
25
  import { createHash as createHash4 } from "crypto";
@@ -479,7 +483,7 @@ function loadSkillAsCommand(loaded) {
479
483
  config.subtask = loaded.subtask;
480
484
  return config;
481
485
  }
482
- function collectAgents(dir, disabledAgents, nativeAgents, overlays) {
486
+ function collectAgents(dir, disabledAgents, nativeAgents, overlays, rawOverlays) {
483
487
  const agents = {};
484
488
  const agentList = findAgentsInDir(dir);
485
489
  const disabledSet = new Set(disabledAgents);
@@ -494,12 +498,16 @@ function collectAgents(dir, disabledAgents, nativeAgents, overlays) {
494
498
  continue;
495
499
  const config = loadAgentAsConfig(agentInfo);
496
500
  if (config) {
497
- agents[agentInfo.name] = applyAgentOverlays(config, agentInfo, overlays);
501
+ agents[agentInfo.name] = applyAgentOverlays(config, agentInfo, overlays, rawOverlays);
498
502
  }
499
503
  }
500
504
  return agents;
501
505
  }
502
- function applyAgentOverlays(config, agentInfo, overlays) {
506
+ var EMPTY_PI_SUBAGENTS_OVERLAYS = {
507
+ agents: {},
508
+ categories: {}
509
+ };
510
+ function applyAgentOverlays(config, agentInfo, overlays, rawOverlays) {
503
511
  const id = agentInfo.category ? `${agentInfo.category}/${agentInfo.name}` : agentInfo.name;
504
512
  const categoryOverlay = agentInfo.category ? overlays.categoriesByKey.get(agentInfo.category) : undefined;
505
513
  const exactOverlay = overlays.agentsByTargetId.get(id);
@@ -509,15 +517,40 @@ function applyAgentOverlays(config, agentInfo, overlays) {
509
517
  if (hasPermissionOverlay && isRecord(config.permission)) {
510
518
  addPermissionRules(permissionRules, config.permission);
511
519
  }
512
- applyAgentOverlay(result, categoryOverlay?.value, permissionRules);
513
- applyAgentOverlay(result, exactOverlay?.value, permissionRules);
520
+ const routing = resolveRouting({
521
+ overlays: rawOverlays,
522
+ piSubagentsOverlays: EMPTY_PI_SUBAGENTS_OVERLAYS,
523
+ target: { agentKey: agentInfo.name, category: agentInfo.category ?? "" },
524
+ harness: "opencode"
525
+ });
526
+ applyAgentOverlayPass(result, categoryOverlay?.value, permissionRules, routing, "category");
527
+ applyAgentOverlayPass(result, exactOverlay?.value, permissionRules, routing, "agent");
514
528
  applyPermissionOverlay(result, permissionRules, hasPermissionOverlay);
515
529
  return result;
516
530
  }
517
- function applyAgentOverlay(target, overlay, permissionRules) {
531
+ function applyAgentOverlayPass(target, overlay, permissionRules, routing, level) {
532
+ if (routing.source.model?.level === level) {
533
+ applyRoutingModel(target, routing.model);
534
+ }
535
+ if (routing.source.qualifier?.level === level) {
536
+ target.variant = routing.qualifier;
537
+ }
518
538
  if (overlay === undefined)
519
539
  return;
520
- applyOverlayObjectWithVariantClearing(target, overlay, permissionRules);
540
+ applyOverlayObjectFields(target, overlay);
541
+ if (isRecord(overlay.permission)) {
542
+ addPermissionRules(permissionRules, overlay.permission);
543
+ }
544
+ if (Array.isArray(overlay.skills)) {
545
+ addManagedSkillRules(permissionRules, overlay.skills);
546
+ }
547
+ }
548
+ function applyRoutingModel(target, model) {
549
+ if (model === null) {
550
+ delete target.model;
551
+ } else if (model !== undefined) {
552
+ target.model = model;
553
+ }
521
554
  }
522
555
  function applyPermissionOverlay(target, permissionRules, hasPermissionOverlay) {
523
556
  if (!hasPermissionOverlay)
@@ -533,8 +566,6 @@ function overlayControlsPermission(overlay) {
533
566
  return overlay !== undefined && (Object.hasOwn(overlay, "permission") || Object.hasOwn(overlay, "skills"));
534
567
  }
535
568
  var OVERLAY_ASSIGN_FIELDS = [
536
- "model",
537
- "variant",
538
569
  "temperature",
539
570
  "top_p",
540
571
  "mode",
@@ -542,27 +573,12 @@ var OVERLAY_ASSIGN_FIELDS = [
542
573
  "steps",
543
574
  "hidden"
544
575
  ];
545
- function applyOverlayObjectWithVariantClearing(target, overlay, permissionRules) {
546
- const overlayHasModel = Object.hasOwn(overlay, "model");
547
- const overlayHasVariant = Object.hasOwn(overlay, "variant");
548
- if (overlayHasModel && !overlayHasVariant) {
549
- delete target.variant;
550
- }
576
+ function applyOverlayObjectFields(target, overlay) {
551
577
  for (const field of OVERLAY_ASSIGN_FIELDS) {
552
578
  if (Object.hasOwn(overlay, field)) {
553
- if (field === "model" && overlay[field] === null) {
554
- delete target[field];
555
- } else {
556
- target[field] = overlay[field];
557
- }
579
+ target[field] = overlay[field];
558
580
  }
559
581
  }
560
- if (isRecord(overlay.permission)) {
561
- addPermissionRules(permissionRules, overlay.permission);
562
- }
563
- if (Array.isArray(overlay.skills)) {
564
- addManagedSkillRules(permissionRules, overlay.skills);
565
- }
566
582
  }
567
583
  function createPermissionRuleAccumulator() {
568
584
  return new Map;
@@ -705,7 +721,7 @@ function createConfigHandler(deps) {
705
721
  enabledSkills: enabledSkillNames
706
722
  });
707
723
  const resolvedOverlays = resolveAgentOverlaySet(validatedOverlays);
708
- const bundledAgents = collectAgents(bundledAgentsDir, systematicConfig.disabled_agents, nativeAgents, resolvedOverlays);
724
+ const bundledAgents = collectAgents(bundledAgentsDir, systematicConfig.disabled_agents, nativeAgents, resolvedOverlays, overlays);
709
725
  const bundledCommands = collectCommands(bundledCommandsDir, systematicConfig.disabled_commands);
710
726
  const discoveredSkillCommands = systematicConfig.skills_as_commands !== false ? collectDiscoveredSkillsAsCommands(directory, homeDir, opencodeConfigDir, opencodeConfigDirOverride, systematicConfig.disabled_commands) : {};
711
727
  const bundledAgentKeys = new Set(Object.keys(bundledAgents));
@@ -731,14 +747,14 @@ function registerSkillsPaths(config, skillsDir) {
731
747
  };
732
748
  }
733
749
  function removeSystematicSkillPaths(paths) {
734
- return paths.filter((path5) => !isSystematicSkillPath(path5));
750
+ return paths.filter((path) => !isSystematicSkillPath(path));
735
751
  }
736
- function isSystematicSkillPath(path5) {
737
- const normalizedPath = normalizePath(path5);
752
+ function isSystematicSkillPath(path) {
753
+ const normalizedPath = normalizePath(path);
738
754
  return normalizedPath.endsWith("/.config/opencode/systematic/skills") || normalizedPath.endsWith("/.cache/opencode/systematic/skills") || normalizedPath.endsWith("/.local/share/opencode/systematic/skills") || normalizedPath.endsWith("/.opencode/systematic/skills") || /(?:^|\/)\.cache\/opencode\/packages\/@fro\.bot\/systematic@[^/]+\/node_modules\/@fro\.bot\/systematic\/skills(?:$|\/)/u.test(normalizedPath);
739
755
  }
740
- function normalizePath(path5) {
741
- return path5.replaceAll("\\", "/").replace(/\/+$/u, "");
756
+ function normalizePath(path) {
757
+ return path.replaceAll("\\", "/").replace(/\/+$/u, "");
742
758
  }
743
759
 
744
760
  // src/lib/opencode-operation-observer.ts
@@ -1655,10 +1671,10 @@ function createQuestionAttestation(options = {}) {
1655
1671
  const disabledSessions = new Set;
1656
1672
  let challengeCounter = 0;
1657
1673
  function expireChallenges(now) {
1658
- for (const [challengeId, challenge2] of challenges) {
1659
- if ((challenge2.state === "pending" || challenge2.state === "bound") && now - challenge2.createdAt > maxChallengeAgeMs) {
1660
- challenge2.state = "expired";
1661
- const key = bindingKey(challenge2, challenge2.resourceDigest);
1674
+ for (const [challengeId, challenge] of challenges) {
1675
+ if ((challenge.state === "pending" || challenge.state === "bound") && now - challenge.createdAt > maxChallengeAgeMs) {
1676
+ challenge.state = "expired";
1677
+ const key = bindingKey(challenge, challenge.resourceDigest);
1662
1678
  if (activeByBinding.get(key) === challengeId)
1663
1679
  activeByBinding.delete(key);
1664
1680
  }
@@ -1675,17 +1691,17 @@ function createQuestionAttestation(options = {}) {
1675
1691
  function findBindChallenge(input) {
1676
1692
  return "challengeId" in input ? findChallengeById(input.challengeId) : findChallengeByScope(input);
1677
1693
  }
1678
- function bindStateRejection(challenge2, input) {
1679
- if (challenge2.state === "expired")
1694
+ function bindStateRejection(challenge, input) {
1695
+ if (challenge.state === "expired")
1680
1696
  return "challenge-expired";
1681
- if (challenge2.state === "denied" || challenge2.state === "consumed") {
1697
+ if (challenge.state === "denied" || challenge.state === "consumed") {
1682
1698
  return "challenge-consumed";
1683
1699
  }
1684
- if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !== challenge2.sessionId) {
1700
+ if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !== challenge.sessionId) {
1685
1701
  return "call-session-mismatch";
1686
1702
  }
1687
- if (challenge2.state === "bound") {
1688
- return challenge2.requestId === input.requestId ? "already-bound" : "substitution";
1703
+ if (challenge.state === "bound") {
1704
+ return challenge.requestId === input.requestId ? "already-bound" : "substitution";
1689
1705
  }
1690
1706
  return seenRequestIds.has(input.requestId) ? "replay" : null;
1691
1707
  }
@@ -1693,23 +1709,23 @@ function createQuestionAttestation(options = {}) {
1693
1709
  const challengeId = challengeByRequest.get(requestId);
1694
1710
  return challengeId === undefined ? null : challenges.get(challengeId) ?? null;
1695
1711
  }
1696
- function replyStateRejection(challenge2, input) {
1697
- if (challenge2.sessionId !== input.sessionId)
1712
+ function replyStateRejection(challenge, input) {
1713
+ if (challenge.sessionId !== input.sessionId)
1698
1714
  return "substitution";
1699
- if (challenge2.state === "expired")
1715
+ if (challenge.state === "expired")
1700
1716
  return "challenge-expired";
1701
- if (challenge2.state !== "bound" || challenge2.requestId !== input.requestId) {
1717
+ if (challenge.state !== "bound" || challenge.requestId !== input.requestId) {
1702
1718
  return "replay";
1703
1719
  }
1704
1720
  return null;
1705
1721
  }
1706
- function rejectStateRejection(challenge2, input) {
1707
- if (challenge2.sessionId !== input.sessionId)
1722
+ function rejectStateRejection(challenge, input) {
1723
+ if (challenge.sessionId !== input.sessionId)
1708
1724
  return "substitution";
1709
- if (challenge2.state === "denied" || challenge2.state === "consumed") {
1725
+ if (challenge.state === "denied" || challenge.state === "consumed") {
1710
1726
  return "already-consumed";
1711
1727
  }
1712
- if (challenge2.state === "expired")
1728
+ if (challenge.state === "expired")
1713
1729
  return "challenge-expired";
1714
1730
  return null;
1715
1731
  }
@@ -1721,37 +1737,37 @@ function createQuestionAttestation(options = {}) {
1721
1737
  const parsed = parseBinding(input);
1722
1738
  return parsed === null ? null : findChallengeByScope(parsed);
1723
1739
  }
1724
- function projectionBase(challenge2, status2) {
1740
+ function projectionBase(challenge, status) {
1725
1741
  return {
1726
- status: status2,
1727
- challengeId: challenge2.challengeId,
1728
- purpose: challenge2.purpose,
1729
- sessionId: challenge2.sessionId,
1730
- resourceDigest: challenge2.resourceDigest,
1731
- transitionKey: challenge2.transition,
1732
- ...challenge2.requestId === undefined ? {} : { requestId: challenge2.requestId }
1742
+ status,
1743
+ challengeId: challenge.challengeId,
1744
+ purpose: challenge.purpose,
1745
+ sessionId: challenge.sessionId,
1746
+ resourceDigest: challenge.resourceDigest,
1747
+ transitionKey: challenge.transition,
1748
+ ...challenge.requestId === undefined ? {} : { requestId: challenge.requestId }
1733
1749
  };
1734
1750
  }
1735
- function projectChallenge(challenge2) {
1736
- const attestation = challenge2.requestId === undefined ? undefined : attestations.get(challenge2.requestId);
1751
+ function projectChallenge(challenge) {
1752
+ const attestation = challenge.requestId === undefined ? undefined : attestations.get(challenge.requestId);
1737
1753
  if (attestation !== undefined) {
1738
- const status2 = attestation.purpose === "session-disablement" && attestation.consumption === "consumed" ? "disabled" : "attested";
1754
+ const status = attestation.purpose === "session-disablement" && attestation.consumption === "consumed" ? "disabled" : "attested";
1739
1755
  return {
1740
- ...projectionBase(challenge2, status2),
1756
+ ...projectionBase(challenge, status),
1741
1757
  consumption: attestation.consumption
1742
1758
  };
1743
1759
  }
1744
- if (challenge2.state === "pending" || challenge2.state === "bound") {
1745
- return projectionBase(challenge2, challenge2.state);
1760
+ if (challenge.state === "pending" || challenge.state === "bound") {
1761
+ return projectionBase(challenge, challenge.state);
1746
1762
  }
1747
- if (challenge2.state === "denied") {
1748
- return projectionBase(challenge2, "denied");
1763
+ if (challenge.state === "denied") {
1764
+ return projectionBase(challenge, "denied");
1749
1765
  }
1750
1766
  return { status: "unknown", reasonCode: "challenge-expired" };
1751
1767
  }
1752
- function removeActiveChallenge(challenge2) {
1753
- const key = bindingKey(challenge2, challenge2.resourceDigest);
1754
- if (activeByBinding.get(key) === challenge2.challengeId) {
1768
+ function removeActiveChallenge(challenge) {
1769
+ const key = bindingKey(challenge, challenge.resourceDigest);
1770
+ if (activeByBinding.get(key) === challenge.challengeId) {
1755
1771
  activeByBinding.delete(key);
1756
1772
  }
1757
1773
  }
@@ -1800,20 +1816,20 @@ function createQuestionAttestation(options = {}) {
1800
1816
  if (parsed === null)
1801
1817
  return rejected("invalid-input");
1802
1818
  expireChallenges(readNow(clock));
1803
- const challenge2 = findBindChallenge(parsed);
1804
- if (challenge2 === null)
1819
+ const challenge = findBindChallenge(parsed);
1820
+ if (challenge === null)
1805
1821
  return rejected("unknown-challenge");
1806
- const stateRejection = bindStateRejection(challenge2, parsed);
1822
+ const stateRejection = bindStateRejection(challenge, parsed);
1807
1823
  if (stateRejection !== null)
1808
1824
  return rejected(stateRejection);
1809
- challenge2.state = "bound";
1810
- challenge2.callId = parsed.callId;
1811
- challenge2.requestId = parsed.requestId;
1812
- challengeByRequest.set(parsed.requestId, challenge2.challengeId);
1825
+ challenge.state = "bound";
1826
+ challenge.callId = parsed.callId;
1827
+ challenge.requestId = parsed.requestId;
1828
+ challengeByRequest.set(parsed.requestId, challenge.challengeId);
1813
1829
  seenRequestIds.add(parsed.requestId);
1814
1830
  return {
1815
1831
  status: "bound",
1816
- challengeId: challenge2.challengeId,
1832
+ challengeId: challenge.challengeId,
1817
1833
  requestId: parsed.requestId
1818
1834
  };
1819
1835
  } catch {
@@ -1826,32 +1842,32 @@ function createQuestionAttestation(options = {}) {
1826
1842
  if (parsed === null)
1827
1843
  return rejected("invalid-input");
1828
1844
  expireChallenges(readNow(clock));
1829
- const challenge2 = requestChallenge(parsed.requestId);
1830
- if (challenge2 === null) {
1845
+ const challenge = requestChallenge(parsed.requestId);
1846
+ if (challenge === null) {
1831
1847
  const replay = seenRequestIds.has(parsed.requestId);
1832
1848
  seenRequestIds.add(parsed.requestId);
1833
1849
  return rejected(replay ? "replay" : "unknown-request");
1834
1850
  }
1835
- const stateRejection = replyStateRejection(challenge2, parsed);
1851
+ const stateRejection = replyStateRejection(challenge, parsed);
1836
1852
  if (stateRejection !== null)
1837
1853
  return rejected(stateRejection);
1838
1854
  if (classifyQuestionAnswer(parsed.answer) !== "affirmative") {
1839
- challenge2.state = "denied";
1840
- removeActiveChallenge(challenge2);
1855
+ challenge.state = "denied";
1856
+ removeActiveChallenge(challenge);
1841
1857
  return rejected("non-affirmative");
1842
1858
  }
1843
1859
  const attestation = {
1844
- purpose: challenge2.purpose,
1845
- sessionId: challenge2.sessionId,
1846
- resourceDigest: challenge2.resourceDigest,
1847
- transitionKey: challenge2.transition,
1860
+ purpose: challenge.purpose,
1861
+ sessionId: challenge.sessionId,
1862
+ resourceDigest: challenge.resourceDigest,
1863
+ transitionKey: challenge.transition,
1848
1864
  requestId: parsed.requestId,
1849
1865
  answer: "affirmed",
1850
1866
  timestamp: readNow(clock),
1851
1867
  consumption: "available"
1852
1868
  };
1853
- challenge2.state = "consumed";
1854
- removeActiveChallenge(challenge2);
1869
+ challenge.state = "consumed";
1870
+ removeActiveChallenge(challenge);
1855
1871
  attestations.set(parsed.requestId, attestation);
1856
1872
  return { status: "accepted", attestation: cloneAttestation(attestation) };
1857
1873
  } catch {
@@ -1864,17 +1880,17 @@ function createQuestionAttestation(options = {}) {
1864
1880
  if (parsed === null)
1865
1881
  return rejected("invalid-input");
1866
1882
  expireChallenges(readNow(clock));
1867
- const challenge2 = requestChallenge(parsed.requestId);
1868
- if (challenge2 === null) {
1883
+ const challenge = requestChallenge(parsed.requestId);
1884
+ if (challenge === null) {
1869
1885
  const replay = seenRequestIds.has(parsed.requestId);
1870
1886
  seenRequestIds.add(parsed.requestId);
1871
1887
  return rejected(replay ? "replay" : "unknown-request");
1872
1888
  }
1873
- const stateRejection = rejectStateRejection(challenge2, parsed);
1889
+ const stateRejection = rejectStateRejection(challenge, parsed);
1874
1890
  if (stateRejection !== null)
1875
1891
  return rejected(stateRejection);
1876
- challenge2.state = "denied";
1877
- removeActiveChallenge(challenge2);
1892
+ challenge.state = "denied";
1893
+ removeActiveChallenge(challenge);
1878
1894
  return { status: "rejected", reasonCode: "rejected" };
1879
1895
  } catch {
1880
1896
  return rejected("invalid-input");
@@ -1924,10 +1940,10 @@ function createQuestionAttestation(options = {}) {
1924
1940
  ])) {
1925
1941
  return { status: "unknown", reasonCode: "invalid-input" };
1926
1942
  }
1927
- const challenge2 = statusChallenge(input);
1928
- if (challenge2 === null)
1943
+ const challenge = statusChallenge(input);
1944
+ if (challenge === null)
1929
1945
  return { status: "unknown", reasonCode: "unknown-challenge" };
1930
- return projectChallenge(challenge2);
1946
+ return projectChallenge(challenge);
1931
1947
  } catch {
1932
1948
  return { status: "unknown", reasonCode: "invalid-input" };
1933
1949
  }
@@ -1941,9 +1957,9 @@ function createQuestionAttestation(options = {}) {
1941
1957
  const sessionId = input.sessionId;
1942
1958
  if (disabledSessions.has(sessionId))
1943
1959
  return { status: "disabled", sessionId };
1944
- for (const challenge2 of challenges.values()) {
1945
- if (challenge2.sessionId === sessionId && challenge2.purpose === "session-disablement" && (challenge2.state === "pending" || challenge2.state === "bound")) {
1946
- return { status: challenge2.state, sessionId };
1960
+ for (const challenge of challenges.values()) {
1961
+ if (challenge.sessionId === sessionId && challenge.purpose === "session-disablement" && (challenge.state === "pending" || challenge.state === "bound")) {
1962
+ return { status: challenge.state, sessionId };
1947
1963
  }
1948
1964
  }
1949
1965
  return { status: "enabled", sessionId };
@@ -3862,10 +3878,10 @@ function createReceiptLedger(options = {}) {
3862
3878
  return { status: "consumed", receipt: cloneEnvelope2(stored.envelope) };
3863
3879
  }
3864
3880
  function recoverReceipt(input, operationTargetIdentity) {
3865
- const markerResult2 = getMintMarker(input);
3866
- if (markerResult2.status !== "valid")
3867
- return markerResult2;
3868
- const marker = markerResult2.marker;
3881
+ const markerResult = getMintMarker(input);
3882
+ if (markerResult.status !== "valid")
3883
+ return markerResult;
3884
+ const marker = markerResult.marker;
3869
3885
  if (marker.sessionSalt !== sessionSalt)
3870
3886
  return { status: "rejected", category: "salt-mismatch" };
3871
3887
  if (marker.envelope.schemaVersion === 1 && operationTargetIdentity !== undefined) {
@@ -4990,8 +5006,8 @@ var Language = class _Language {
4990
5006
  if (input instanceof Uint8Array) {
4991
5007
  binary2 = input;
4992
5008
  } else if (globalThis.process?.versions.node) {
4993
- const fs22 = await import("fs/promises");
4994
- binary2 = await fs22.readFile(input);
5009
+ const fs2 = await import("fs/promises");
5010
+ binary2 = await fs2.readFile(input);
4995
5011
  } else {
4996
5012
  const response = await fetch(input);
4997
5013
  if (!response.ok) {
@@ -5042,11 +5058,11 @@ async function Module2(moduleArg = {}) {
5042
5058
  }, "quit_");
5043
5059
  var _scriptName = import.meta.url;
5044
5060
  var scriptDirectory = "";
5045
- function locateFile(path6) {
5061
+ function locateFile(path) {
5046
5062
  if (Module["locateFile"]) {
5047
- return Module["locateFile"](path6, scriptDirectory);
5063
+ return Module["locateFile"](path, scriptDirectory);
5048
5064
  }
5049
- return scriptDirectory + path6;
5065
+ return scriptDirectory + path;
5050
5066
  }
5051
5067
  __name(locateFile, "locateFile");
5052
5068
  var readAsync, readBinary;
@@ -9744,23 +9760,23 @@ function createWorkflowGuard(options) {
9744
9760
  return recoveryUnitProgressionReason(progression);
9745
9761
  }
9746
9762
  function recoveryUnitProgressionReason(progression) {
9747
- const epoch2 = progression.epoch;
9763
+ const epoch = progression.epoch;
9748
9764
  const unit = progression.unit;
9749
- if (!epoch2)
9765
+ if (!epoch)
9750
9766
  return "invalid-recovery";
9751
9767
  if (!unit) {
9752
- return epoch2.state === "completed" ? "invalid-recovery" : undefined;
9768
+ return epoch.state === "completed" ? "invalid-recovery" : undefined;
9753
9769
  }
9754
- const declarationFailure = recoveryUnitDeclarationReason(epoch2, unit);
9770
+ const declarationFailure = recoveryUnitDeclarationReason(epoch, unit);
9755
9771
  if (declarationFailure)
9756
9772
  return declarationFailure;
9757
- return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(epoch2, unit);
9773
+ return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(epoch, unit);
9758
9774
  }
9759
- function recoveryUnitDeclarationReason(epoch2, unit) {
9760
- return unit.epochId === epoch2.epochId && unit.epochDigest === epoch2.epochDigest && unit.unitDigest === options.ledger.digestIdentity("unit", unit.unitId) && unit.family === epoch2.family ? undefined : "invalid-recovery";
9775
+ function recoveryUnitDeclarationReason(epoch, unit) {
9776
+ return unit.epochId === epoch.epochId && unit.epochDigest === epoch.epochDigest && unit.unitDigest === options.ledger.digestIdentity("unit", unit.unitId) && unit.family === epoch.family ? undefined : "invalid-recovery";
9761
9777
  }
9762
- function recoveryCompletedPairReason(epoch2, unit) {
9763
- return epoch2.state === "completed" && unit.state !== "completed" ? "invalid-recovery" : undefined;
9778
+ function recoveryCompletedPairReason(epoch, unit) {
9779
+ return epoch.state === "completed" && unit.state !== "completed" ? "invalid-recovery" : undefined;
9764
9780
  }
9765
9781
  function recoveryBoundaryReason(envelope) {
9766
9782
  if (envelope.canonical.workspaceDigest !== options.ledger.digestIdentity("workspace", currentWorkspaceIdentity)) {
@@ -9857,8 +9873,8 @@ function createWorkflowGuard(options) {
9857
9873
  }
9858
9874
  return;
9859
9875
  }
9860
- function recoveryEpochCompletionReason(epoch2, matching) {
9861
- if (epoch2?.state !== "completed")
9876
+ function recoveryEpochCompletionReason(epoch, matching) {
9877
+ if (epoch?.state !== "completed")
9862
9878
  return;
9863
9879
  return matching.length > 0 && matching.every((envelope) => envelope.canonical.consumption === "consumed") ? undefined : "invalid-recovery";
9864
9880
  }
@@ -10291,18 +10307,18 @@ function isWorkflowGuardBlockedError(value) {
10291
10307
  return typeof candidate.reasonCode === "string" && REASON_CODES.has(candidate.reasonCode);
10292
10308
  }
10293
10309
  var startToolShape = {
10294
- expected_operations: exports_external.array(exports_external.enum(OPERATIONS)).optional(),
10295
- resource_scopes: exports_external.record(exports_external.string(), exports_external.string()).optional()
10310
+ expected_operations: array(_enum(OPERATIONS)).optional(),
10311
+ resource_scopes: record(string(), string()).optional()
10296
10312
  };
10297
- var completeToolShape = { target: exports_external.enum(["unit", "epoch"]) };
10313
+ var completeToolShape = { target: _enum(["unit", "epoch"]) };
10298
10314
  var controlToolShape = {
10299
- mode: exports_external.enum(["protected", "disabled", "unavailable"])
10315
+ mode: _enum(["protected", "disabled", "unavailable"])
10300
10316
  };
10301
10317
  var statusToolShape = {};
10302
- var startToolSchema = exports_external.object(startToolShape).strict();
10303
- var completeToolSchema = exports_external.object(completeToolShape).strict();
10304
- var controlToolSchema = exports_external.object(controlToolShape).strict();
10305
- var statusToolSchema = exports_external.object(statusToolShape).strict();
10318
+ var startToolSchema = object(startToolShape).strict();
10319
+ var completeToolSchema = object(completeToolShape).strict();
10320
+ var controlToolSchema = object(controlToolShape).strict();
10321
+ var statusToolSchema = object(statusToolShape).strict();
10306
10322
  function isRecord7(value) {
10307
10323
  return typeof value === "object" && value !== null && !Array.isArray(value);
10308
10324
  }
@@ -10453,13 +10469,13 @@ function validationForCandidate(candidatePath, options, targetPath = candidatePa
10453
10469
  }
10454
10470
  function deriveFileTarget(rawPath, baseDirectory, parentTargetRoot, options, realPath, allowParentFastPath = true) {
10455
10471
  const resolvedPath = path6.resolve(baseDirectory, rawPath);
10456
- const canonicalPath2 = canonicalFileTarget(resolvedPath, realPath);
10457
- if (!canonicalPath2)
10472
+ const canonicalPath = canonicalFileTarget(resolvedPath, realPath);
10473
+ if (!canonicalPath)
10458
10474
  return unavailableOperationTarget();
10459
- const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot, canonicalPath2) : undefined;
10475
+ const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot, canonicalPath) : undefined;
10460
10476
  if (parentResult)
10461
10477
  return parentResult;
10462
- return validationForCandidate(path6.dirname(canonicalPath2), options, canonicalPath2);
10478
+ return validationForCandidate(path6.dirname(canonicalPath), options, canonicalPath);
10463
10479
  }
10464
10480
  function sharedTargetRoot(targets, extraRoots = []) {
10465
10481
  const roots = [...extraRoots];
@@ -11057,7 +11073,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11057
11073
  return classifyQuestionAnswer(answer) === "affirmative" ? answer : "no";
11058
11074
  }
11059
11075
  function challengeForTransition(sessionID, target) {
11060
- const existing = [...pendingQuestionChallenges.values()].find((pending2) => pending2.purpose === "transition" && pending2.transition === target);
11076
+ const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "transition" && pending.transition === target);
11061
11077
  if (existing)
11062
11078
  return existing;
11063
11079
  const resource = questionResource(target);
@@ -11079,7 +11095,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11079
11095
  return pending;
11080
11096
  }
11081
11097
  function challengeForDisablement(sessionID) {
11082
- const existing = [...pendingQuestionChallenges.values()].find((pending2) => pending2.purpose === "session-disablement");
11098
+ const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "session-disablement");
11083
11099
  if (existing)
11084
11100
  return existing;
11085
11101
  const resource = `session/${sessionID}`;
@@ -11253,14 +11269,14 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11253
11269
  }
11254
11270
  return;
11255
11271
  }
11256
- function candidateAgreesWithOwnIdentity(salt, digest2) {
11272
+ function candidateAgreesWithOwnIdentity(salt, digest) {
11257
11273
  try {
11258
11274
  const probe = createReceiptLedger({
11259
11275
  capabilityFlags: ["workflow-guard"],
11260
11276
  registrationIdentity: options.registrationIdentity,
11261
11277
  sessionSalt: salt
11262
11278
  });
11263
- return probe.metadata.registrationDigest === digest2;
11279
+ return probe.metadata.registrationDigest === digest;
11264
11280
  } catch {
11265
11281
  return false;
11266
11282
  }
@@ -12465,7 +12481,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
12465
12481
  return;
12466
12482
  }
12467
12483
  }
12468
- function buildOperationObservation(host, pending, after2, current, output, operation = operationCandidate(host.tool), remoteAfter) {
12484
+ function buildOperationObservation(host, pending, after, current, output, operation = operationCandidate(host.tool), remoteAfter) {
12469
12485
  if (!current.epoch || !current.unit || !isLocalOperationTool(host.tool)) {
12470
12486
  return;
12471
12487
  }
@@ -12489,10 +12505,10 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
12489
12505
  },
12490
12506
  after: {
12491
12507
  workspaceIdentity: options.workspaceIdentity,
12492
- repositoryIdentity: after2.repositoryRevisionDigest,
12493
- worktreeIdentity: after2.worktreeRevisionDigest,
12508
+ repositoryIdentity: after.repositoryRevisionDigest,
12509
+ worktreeIdentity: after.worktreeRevisionDigest,
12494
12510
  ...localOperation(operation) ? { operationTargetIdentity: pending.targetIdentity } : {},
12495
- commitClosure: after2.commitClosure,
12511
+ commitClosure: after.commitClosure,
12496
12512
  ...remoteAfter ? {
12497
12513
  resourceIdentity: remoteAfter.resourceIdentity,
12498
12514
  resourceRevisionIdentity: remoteAfter.resourceRevisionIdentity,
@@ -13093,7 +13109,7 @@ function createSkillTool(options) {
13093
13109
  return cachedDescription;
13094
13110
  },
13095
13111
  args: {
13096
- name: exports_external.string().describe((() => {
13112
+ name: string().describe((() => {
13097
13113
  if (cachedParameterHint == null) {
13098
13114
  cachedParameterHint = buildParameterHint();
13099
13115
  }
@@ -1,7 +1,7 @@
1
1
  /** Runtime persona catalog for `systematic_delegate`. Pi has no agent-discovery of its own, so category is dropped when flattening `agents/<category>/<name>.md` into this catalog. */
2
2
  /** A single resolved persona entry in the flattened catalog. */
3
3
  export interface AgentCatalogEntry {
4
- /** Flat persona name (category dropped). */
4
+ /** Flat persona name (category dropped). Used for dispatch matching (`resolveAgent`); may differ from `key` if frontmatter `name` and the file stem diverge. */
5
5
  name: string;
6
6
  /** Human-readable description, used in tool description/parameter hints. */
7
7
  description: string;
@@ -9,6 +9,12 @@ export interface AgentCatalogEntry {
9
9
  body: string;
10
10
  /** Raw comma-separated `tools:` frontmatter value, if declared. Undefined = not declared. */
11
11
  toolsSource: string | undefined;
12
+ /** The agent's source file stem (filename without `.md`), used to key into `agents.<key>` overlays for routing (distinct from the display `name`). */
13
+ key: string;
14
+ /** The agent's category (source subdirectory name), used to key into `categories.<category>` overlays. `''` when the file has no category subdirectory -- the same no-category sentinel `config-handler.ts` and `pi-subagents-export.ts` use. */
15
+ category: string;
16
+ /** Qualified `category/key` id, mirroring `agent-overlays.ts`'s target-id convention, for callers that want a single stable identity. */
17
+ id: string;
12
18
  }
13
19
  /** Fails closed if the same persona name appears under more than one category. */
14
20
  export declare function buildAgentCatalog(agentsDir: string): AgentCatalogEntry[];
@@ -3,7 +3,7 @@ declare const CAPABILITY_SNAPSHOT_COMMAND: 'systematic capabilities';
3
3
  declare const CAPABILITY_SOURCE_IDS: readonly ['config:custom', 'config:global', 'config:project', 'config:user', 'discovery:agents', 'discovery:skills', 'host:runtime', 'package'];
4
4
  declare const CONFIG_SOURCE_KINDS: readonly ['custom', 'project', 'user'];
5
5
  declare const CONFIG_AUTHORITY_FIELD_PATHS: readonly ['bootstrap.enabled', 'bootstrap.file', 'skills_as_commands', 'workflow_guard.debug', 'workflow_guard.mode'];
6
- declare const CONFIG_PROTECTED_FIELD_PATHS: readonly ['workflow_guard', 'agents.*.model', 'agents.*.permission', 'agents.*.skills', 'agents.*.variant', 'categories.*.model', 'categories.*.permission', 'categories.*.skills', 'categories.*.variant'];
6
+ declare const CONFIG_PROTECTED_FIELD_PATHS: readonly ['workflow_guard', 'profiles', 'agents.*.model', 'agents.*.permission', 'agents.*.skills', 'agents.*.variant', 'agents.*.opencode', 'agents.*.pi', 'categories.*.model', 'categories.*.permission', 'categories.*.skills', 'categories.*.variant', 'categories.*.opencode', 'categories.*.pi'];
7
7
  declare const CONFIG_SOURCE_ERROR_CODES: readonly ['parse-failed', 'read-failed', 'schema-invalid', 'source-invalid'];
8
8
  declare const CAPABILITY_SOURCE_PRESENCE: readonly ['absent', 'invalid', 'present'];
9
9
  declare const CAPABILITY_STATUSES: readonly ['available', 'unknown', 'unavailable'];