sneakoscope 8.1.2 → 8.2.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.
Files changed (261) hide show
  1. package/README.md +96 -58
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +5 -51
  5. package/dist/cli/command-manifest-lite.js +2 -1
  6. package/dist/cli/command-registry.js +2 -1
  7. package/dist/cli/global-mode-router.js +1 -1
  8. package/dist/cli/install-helpers-codex-lb-config.js +112 -914
  9. package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
  10. package/dist/cli/install-helpers-install-support.js +4 -20
  11. package/dist/cli/install-helpers.js +36 -2716
  12. package/dist/cli/router.js +9 -9
  13. package/dist/commands/bridge-command-output.js +111 -0
  14. package/dist/commands/bridge.js +320 -0
  15. package/dist/commands/codex-app.js +39 -123
  16. package/dist/commands/doctor-helpers.js +380 -0
  17. package/dist/commands/doctor-profile.js +3 -0
  18. package/dist/commands/doctor.js +114 -873
  19. package/dist/commands/mad-sks.js +0 -4
  20. package/dist/config/skills-manifest.json +1 -1
  21. package/dist/core/agents/agent-effort-policy.js +11 -21
  22. package/dist/core/agents/agent-recursion-guard.js +26 -0
  23. package/dist/core/agents/agent-runner-codex-exec.js +7 -9
  24. package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
  25. package/dist/core/architecture-hardening/state/state-service.js +49 -13
  26. package/dist/core/auto-review.js +15 -9
  27. package/dist/core/codex/codex-config-guard.js +8 -0
  28. package/dist/core/codex-adapter.js +8 -10
  29. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
  30. package/dist/core/codex-app/codex-app-launcher.js +10 -12
  31. package/dist/core/codex-app/codex-app-restart.js +10 -12
  32. package/dist/core/codex-app/menubar/constants.js +2 -5
  33. package/dist/core/codex-app/menubar/global-install.js +3 -2
  34. package/dist/core/codex-app/menubar/installer/result.js +23 -0
  35. package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
  36. package/dist/core/codex-app/menubar/installer.js +5 -96
  37. package/dist/core/codex-app/menubar/migration.js +1 -42
  38. package/dist/core/codex-app/openrouter-provider.js +0 -78
  39. package/dist/core/codex-app.js +97 -360
  40. package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
  41. package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
  42. package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
  43. package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
  44. package/dist/core/codex-control/codex-task-runner.js +16 -60
  45. package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
  46. package/dist/core/codex-exec-output-schema.js +11 -13
  47. package/dist/core/codex-lb/bridge-contracts.js +2 -0
  48. package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
  49. package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
  50. package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
  51. package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
  52. package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
  53. package/dist/core/codex-lb/capability-runner.js +505 -201
  54. package/dist/core/codex-lb/codex-lb-env.js +179 -12
  55. package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
  56. package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
  57. package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
  58. package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
  59. package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
  60. package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
  61. package/dist/core/codex-lb/combined-catalog.js +12 -0
  62. package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
  63. package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
  64. package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
  65. package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
  66. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
  67. package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
  68. package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
  69. package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
  70. package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
  71. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
  72. package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
  73. package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
  74. package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
  75. package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
  76. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
  77. package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
  78. package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
  79. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
  80. package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
  81. package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
  82. package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
  83. package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
  84. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
  85. package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
  86. package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
  87. package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
  88. package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
  89. package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
  90. package/dist/core/codex-lb/desktop-controller.js +2 -1730
  91. package/dist/core/codex-lb/desktop-service.js +462 -627
  92. package/dist/core/codex-lb/migration-receipt.js +560 -118
  93. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
  94. package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
  95. package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
  96. package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
  97. package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
  98. package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
  99. package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
  100. package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
  101. package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
  102. package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
  103. package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
  104. package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
  105. package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
  106. package/dist/core/codex-lb/provider-credentials/types.js +1 -0
  107. package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
  108. package/dist/core/codex-lb/provider-credentials.js +5 -0
  109. package/dist/core/codex-lb/provider-registry.js +323 -0
  110. package/dist/core/codex-lb/provider-route-policy.js +118 -0
  111. package/dist/core/codex-lb/request-route-resolver.js +172 -0
  112. package/dist/core/codex-lb/route-index.js +148 -0
  113. package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
  114. package/dist/core/commands/basic-cli.js +1 -1
  115. package/dist/core/commands/check-command.js +3 -10
  116. package/dist/core/commands/gate-result-contract.js +10 -14
  117. package/dist/core/commands/intent-normalization/normalizer.js +1 -1
  118. package/dist/core/commands/mad-sks-command.js +2 -6
  119. package/dist/core/commands/release-command.js +11 -1
  120. package/dist/core/commands/telegram-command.js +46 -6
  121. package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
  122. package/dist/core/doctor/skill-legacy-surface.js +5 -5
  123. package/dist/core/evidence/v2/evidence-key.js +30 -3
  124. package/dist/core/feature-fixtures.js +8 -1
  125. package/dist/core/feature-registry.js +3 -2
  126. package/dist/core/hooks-runtime/stop-finalization.js +11 -1
  127. package/dist/core/hooks-runtime/subagent-context.js +15 -1
  128. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
  129. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  130. package/dist/core/hooks-runtime.js +73 -87
  131. package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
  132. package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
  133. package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
  134. package/dist/core/imagegen/imagegen-capability.js +43 -151
  135. package/dist/core/init/skills/filesystem.js +89 -0
  136. package/dist/core/init/skills/inventory.js +97 -0
  137. package/dist/core/init/skills/manifest.js +151 -0
  138. package/dist/core/init/skills.js +5 -325
  139. package/dist/core/init.js +0 -63
  140. package/dist/core/install/installed-package-smoke.js +1 -1
  141. package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
  142. package/dist/core/policy/latest-version-guidance.js +15 -2
  143. package/dist/core/preflight/parallel-preflight-engine.js +27 -51
  144. package/dist/core/provider/provider-badge.js +9 -4
  145. package/dist/core/provider/provider-context.js +57 -107
  146. package/dist/core/providers/openrouter/openrouter-account.js +3 -1
  147. package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
  148. package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
  149. package/dist/core/release/gate-manifest.js +0 -1
  150. package/dist/core/release/main-push-guard.js +13 -0
  151. package/dist/core/release/main-push-receipt.js +11 -0
  152. package/dist/core/release/physical-release-gates.js +664 -61
  153. package/dist/core/release/publish-preflight.js +3 -3
  154. package/dist/core/release/release-gate-batch-runner.js +19 -6
  155. package/dist/core/release/release-gate-dag.js +33 -6
  156. package/dist/core/release/release-gate-node.js +1 -3
  157. package/dist/core/release/release-gate-output-contract.js +55 -0
  158. package/dist/core/release/release-pack-contract.js +1 -1
  159. package/dist/core/release/release-pack-receipt.js +209 -8
  160. package/dist/core/release/release-real-contract.js +1 -1
  161. package/dist/core/release/stage-publish.js +106 -28
  162. package/dist/core/retention/temp-lease.js +204 -0
  163. package/dist/core/retention.js +18 -195
  164. package/dist/core/routes.js +1 -2
  165. package/dist/core/safety/intent-contract/intent-contract.js +3 -3
  166. package/dist/core/subagents/naruto-host-credentials.js +6 -1
  167. package/dist/core/subagents/official-subagent-config.js +27 -9
  168. package/dist/core/subagents/official-subagent-runner.js +14 -31
  169. package/dist/core/subagents/wave-lifecycle.js +36 -8
  170. package/dist/core/subagents/wave-parent-guidance.js +2 -1
  171. package/dist/core/telegram/doctor.js +2 -2
  172. package/dist/core/telegram/liveness.js +10 -4
  173. package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
  174. package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
  175. package/dist/core/update/update-migration-state/session-state-split.js +247 -0
  176. package/dist/core/update/update-migration-state/simple-stages.js +46 -0
  177. package/dist/core/update/update-migration-state.js +4 -481
  178. package/dist/core/version.js +1 -1
  179. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
  180. package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
  181. package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
  182. package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
  183. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
  184. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
  185. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
  186. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
  187. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
  188. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
  189. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
  190. package/dist/scripts/canonical-test-runner.js +7 -1
  191. package/dist/scripts/check-runtime-schemas.js +7 -2
  192. package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
  193. package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
  194. package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
  195. package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
  196. package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
  197. package/dist/scripts/desktop-bridge-transport-client.js +116 -0
  198. package/dist/scripts/desktop-bridge-unification-check.js +276 -0
  199. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
  200. package/dist/scripts/gate-policy-audit-check.js +52 -2
  201. package/dist/scripts/provider-badge-context-check.js +55 -12
  202. package/dist/scripts/publish-preflight.js +1 -2
  203. package/dist/scripts/release-affected-selector-check.js +1 -2
  204. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  205. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  206. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
  207. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  208. package/dist/scripts/release-gate-batch-runner-check.js +9 -0
  209. package/dist/scripts/release-gate-dag-runner-check.js +6 -0
  210. package/dist/scripts/release-gate-dag-runner.js +4 -2
  211. package/dist/scripts/release-metadata-check.js +16 -3
  212. package/dist/scripts/release-pack-receipt.js +29 -6
  213. package/dist/scripts/release-physical-gates-check.js +39 -0
  214. package/dist/scripts/release-real-check.js +7 -5
  215. package/package.json +6 -8
  216. package/release-gates.v2.json +156 -157
  217. package/runtime-required-scripts.json +11 -11
  218. package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
  219. package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
  220. package/schemas/release/release-gate-node.schema.json +2 -3
  221. package/dist/cli/codex-lb-setup-warning-output.js +0 -17
  222. package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
  223. package/dist/commands/codex-lb.js +0 -1232
  224. package/dist/core/architecture-hardening/migration/migration.js +0 -111
  225. package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
  226. package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
  227. package/dist/core/codex-app/child-policy/child-policy.js +0 -35
  228. package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
  229. package/dist/core/codex-app/glm-model-profile.js +0 -1
  230. package/dist/core/codex-app/glm-profile-installer.js +0 -191
  231. package/dist/core/codex-app/glm-profile-schema.js +0 -42
  232. package/dist/core/codex-app/multi-provider-router.js +0 -391
  233. package/dist/core/codex-app/openrouter-activate.js +0 -405
  234. package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
  235. package/dist/core/codex-app/provider-child-policy.js +0 -64
  236. package/dist/core/codex-app/provider-mode.js +0 -91
  237. package/dist/core/codex-app/provider-session-policy.js +0 -85
  238. package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
  239. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
  240. package/dist/core/codex-lb/codex-lb-setup.js +0 -293
  241. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
  242. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
  243. package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
  244. package/dist/core/codex-lb/desktop-mode.js +0 -32
  245. package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
  246. package/dist/core/codex-lb/legacy-migration.js +0 -576
  247. package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
  248. package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
  249. package/dist/core/codex-lb/routing-truth.js +0 -327
  250. package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
  251. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
  252. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
  253. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
  254. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
  255. package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
  256. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
  257. package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
  258. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
  259. package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
  260. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
  261. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
@@ -0,0 +1,97 @@
1
+ import { PACKAGE_VERSION } from '../../fsx.js';
2
+ import { buildSksCoreSkillManifest, isCoreSkillName, legacyCoreSkillNames } from '../../codex-native/core-skill-manifest.js';
3
+ import { DOLLAR_COMMANDS, DOLLAR_SKILL_NAMES, LEGACY_DOLLAR_SKILL_NAMES, RECOMMENDED_SKILLS } from '../../routes.js';
4
+ export const SKS_SKILL_MANIFEST_FILE = '.sks-generated.json';
5
+ export const PACKAGED_SKILLS_MANIFEST_SCHEMA = 'sks.skills-manifest.v1';
6
+ export const SKILLS_HASH_LEDGER_SCHEMA = 'sks.skills-hash-ledger.v1';
7
+ export const MAX_SKILL_HASH_HISTORY = 8;
8
+ export const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES = [
9
+ 'sks-ux-review',
10
+ 'sks-visual-review',
11
+ 'sks-ui-ux-review'
12
+ ];
13
+ export const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET = new Set(RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES);
14
+ export const REMOVED_SKS_SKILL_NAMES = [
15
+ 'old-workflow',
16
+ 'team-legacy',
17
+ 'team',
18
+ 'agent-team',
19
+ 'agent',
20
+ 'mad-db',
21
+ 'tmux',
22
+ 'xai',
23
+ 'swarm',
24
+ 'shadow-clone',
25
+ 'shadow-clone-legacy',
26
+ 'kage-bunshin',
27
+ 'qaloop',
28
+ 'wiki-refresh',
29
+ 'wikirefresh',
30
+ 'research-discovery',
31
+ 'sks-research-discovery',
32
+ 'ralph',
33
+ 'ralph-supervisor',
34
+ 'ralph-resolver',
35
+ 'loop',
36
+ 'sks-loop'
37
+ ];
38
+ export const LEGACY_SKS_SUPPORT_SKILL_NAMES = [
39
+ 'autoresearch-loop',
40
+ 'context7-docs',
41
+ 'db-safety-guard',
42
+ 'design-artifact-expert',
43
+ 'design-system-builder',
44
+ 'design-ui-editor',
45
+ 'from-chat-img',
46
+ 'getdesign-reference',
47
+ 'gx-visual-generate',
48
+ 'gx-visual-read',
49
+ 'gx-visual-validate',
50
+ 'honest-mode',
51
+ 'hproof-claim-ledger',
52
+ 'hproof-evidence-bind',
53
+ 'imagegen',
54
+ 'imagegen-source-scout',
55
+ 'performance-evaluator',
56
+ 'pipeline-runner',
57
+ 'prompt-pipeline',
58
+ 'reasoning-router',
59
+ 'reflection',
60
+ 'solution-scout',
61
+ 'turbo-context-pack'
62
+ ];
63
+ export const LEGACY_UNPREFIXED_SKS_SKILL_NAMES = Array.from(new Set([
64
+ ...LEGACY_DOLLAR_SKILL_NAMES,
65
+ ...legacyCoreSkillNames(),
66
+ ...LEGACY_SKS_SUPPORT_SKILL_NAMES
67
+ ].map((name) => canonicalSkillNameFromValue(name)).filter((name) => name && name !== 'sks'))).sort();
68
+ export const SKS_SKILL_NAMES_TO_CLEAN_UP = Array.from(new Set([
69
+ ...REMOVED_SKS_SKILL_NAMES,
70
+ ...LEGACY_UNPREFIXED_SKS_SKILL_NAMES
71
+ ]));
72
+ export const REMOVED_SKS_SKILL_NAME_SET = new Set(SKS_SKILL_NAMES_TO_CLEAN_UP);
73
+ export const SKILL_ALIASES = {};
74
+ export function canonicalSkillNameFromValue(value) {
75
+ return String(value || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
76
+ }
77
+ export function buildFallbackSkillsManifest() {
78
+ const names = new Set([
79
+ ...DOLLAR_SKILL_NAMES.map((name) => canonicalSkillNameFromValue(name)),
80
+ ...RECOMMENDED_SKILLS.map((name) => canonicalSkillNameFromValue(name)),
81
+ ...DOLLAR_COMMANDS.map((command) => canonicalSkillNameFromValue(String(command.command || '').replace(/^\$/, ''))),
82
+ ...buildSksCoreSkillManifest().skills.map((skill) => skill.canonical_name)
83
+ ].filter((name) => Boolean(name)
84
+ && !REMOVED_SKS_SKILL_NAME_SET.has(name)
85
+ && !RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET.has(name)));
86
+ return {
87
+ schema: PACKAGED_SKILLS_MANIFEST_SCHEMA,
88
+ package_version: PACKAGE_VERSION,
89
+ skills: [...names].sort().map((name) => ({
90
+ canonical_name: name,
91
+ type: isCoreSkillName(name) ? 'core' : 'official',
92
+ content_sha256: '',
93
+ hash_history: [],
94
+ deprecated_aliases: SKILL_ALIASES[name] || []
95
+ }))
96
+ };
97
+ }
@@ -0,0 +1,151 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { PACKAGE_VERSION, readJson, sha256 } from '../../fsx.js';
5
+ import { isCoreSkillName } from '../../codex-native/core-skill-manifest.js';
6
+ import { MAX_SKILL_HASH_HISTORY, PACKAGED_SKILLS_MANIFEST_SCHEMA, REMOVED_SKS_SKILL_NAME_SET, SKILLS_HASH_LEDGER_SCHEMA, SKILL_ALIASES, buildFallbackSkillsManifest, canonicalSkillNameFromValue } from './inventory.js';
7
+ export async function loadSkillsManifest() {
8
+ const bundled = await loadBundledSkillsManifest();
9
+ if (bundled)
10
+ return bundled;
11
+ const candidates = [
12
+ path.join(path.resolve(process.env.HOME || os.homedir()), '.agents', 'skills', 'skills-manifest.json')
13
+ ];
14
+ return (await loadFirstCompleteSkillsManifest(candidates)) || buildFallbackSkillsManifest();
15
+ }
16
+ export async function loadBundledSkillsManifest() {
17
+ const packaged = await loadFirstCompleteSkillsManifest([
18
+ path.join(packageRootDir(), 'dist', 'config', 'skills-manifest.json'),
19
+ path.join(packageRootDir(), 'config', 'skills-manifest.json')
20
+ ]);
21
+ if (packaged)
22
+ return packaged;
23
+ const ledger = await readJson(path.join(packageRootDir(), 'config', 'skills-hash-ledger.v1.json'), null);
24
+ return skillsManifestFromHashLedger(ledger);
25
+ }
26
+ export function skillsManifestFromHashLedger(ledger) {
27
+ if (ledger?.schema !== SKILLS_HASH_LEDGER_SCHEMA || !Array.isArray(ledger?.skills))
28
+ return null;
29
+ const expected = new Set(buildFallbackSkillsManifest().skills.map((skill) => canonicalSkillNameFromValue(skill.canonical_name)));
30
+ const names = new Set();
31
+ const skills = [];
32
+ for (const row of ledger.skills) {
33
+ const canonicalName = canonicalSkillNameFromValue(row?.canonical_name);
34
+ const trusted = Array.isArray(row?.trusted_sha256)
35
+ ? row.trusted_sha256.map((value) => String(value || '').trim().toLowerCase())
36
+ : [];
37
+ if (!canonicalName
38
+ || canonicalName !== row?.canonical_name
39
+ || names.has(canonicalName)
40
+ || trusted.length < 1
41
+ || trusted.length > MAX_SKILL_HASH_HISTORY + 1
42
+ || trusted.some((digest) => !/^[a-f0-9]{64}$/.test(digest))
43
+ || new Set(trusted).size !== trusted.length)
44
+ return null;
45
+ names.add(canonicalName);
46
+ if (REMOVED_SKS_SKILL_NAME_SET.has(canonicalName))
47
+ continue;
48
+ skills.push({
49
+ canonical_name: canonicalName,
50
+ type: isCoreSkillName(canonicalName) ? 'core' : 'official',
51
+ content_sha256: trusted[0],
52
+ hash_history: trusted.slice(1),
53
+ deprecated_aliases: SKILL_ALIASES[canonicalName] || []
54
+ });
55
+ }
56
+ if ([...expected].some((name) => !names.has(name)))
57
+ return null;
58
+ const manifest = {
59
+ schema: PACKAGED_SKILLS_MANIFEST_SCHEMA,
60
+ package_version: PACKAGE_VERSION,
61
+ skills: skills.sort((left, right) => left.canonical_name.localeCompare(right.canonical_name))
62
+ };
63
+ return skillsManifestHasContentDigests(manifest) ? manifest : null;
64
+ }
65
+ export function normalizeSkillsManifest(manifest) {
66
+ const skills = (manifest.skills || [])
67
+ .map((skill) => ({
68
+ ...skill,
69
+ deprecated_aliases: (skill.deprecated_aliases || [])
70
+ .filter((name) => !REMOVED_SKS_SKILL_NAME_SET.has(canonicalSkillNameFromValue(name)))
71
+ }))
72
+ .filter((skill) => !REMOVED_SKS_SKILL_NAME_SET.has(canonicalSkillNameFromValue(skill.canonical_name)));
73
+ const { removed_skills: _retiredInventory, ...current } = manifest || {};
74
+ return { ...current, skills };
75
+ }
76
+ export function mergePackagedSkillsManifestHashHistory(currentManifest, previousManifest) {
77
+ const previousByName = new Map((Array.isArray(previousManifest?.skills) ? previousManifest.skills : [])
78
+ .map((row) => [canonicalSkillNameFromValue(row?.canonical_name), row])
79
+ .filter(([name]) => Boolean(name)));
80
+ return {
81
+ ...currentManifest,
82
+ skills: (Array.isArray(currentManifest?.skills) ? currentManifest.skills : []).map((row) => {
83
+ const canonicalName = canonicalSkillNameFromValue(row?.canonical_name);
84
+ const currentDigest = String(row?.content_sha256 || '').trim().toLowerCase();
85
+ const previous = previousByName.get(canonicalName);
86
+ const history = [
87
+ previous?.content_sha256,
88
+ ...(Array.isArray(previous?.hash_history) ? previous.hash_history : []),
89
+ ...(Array.isArray(row?.hash_history) ? row.hash_history : [])
90
+ ]
91
+ .map((value) => String(value || '').trim().toLowerCase())
92
+ .filter((value, index, values) => (/^[a-f0-9]{64}$/.test(value)
93
+ && value !== currentDigest
94
+ && values.indexOf(value) === index))
95
+ .slice(0, MAX_SKILL_HASH_HISTORY);
96
+ return { ...row, hash_history: history };
97
+ })
98
+ };
99
+ }
100
+ export function skillManifestGenerationSha256(manifest) {
101
+ if (manifest?.schema !== PACKAGED_SKILLS_MANIFEST_SCHEMA || !Array.isArray(manifest?.skills))
102
+ return null;
103
+ const rows = manifest.skills
104
+ .map((skill) => ({
105
+ canonical_name: canonicalSkillNameFromValue(skill?.canonical_name),
106
+ content_sha256: String(skill?.content_sha256 || '').trim().toLowerCase()
107
+ }))
108
+ .filter((skill) => skill.canonical_name && /^[a-f0-9]{64}$/.test(skill.content_sha256))
109
+ .sort((left, right) => left.canonical_name.localeCompare(right.canonical_name));
110
+ return rows.length ? sha256(JSON.stringify(rows)) : null;
111
+ }
112
+ export async function runtimeBuildSourceTime() {
113
+ const stamp = await readJson(path.join(packageRootDir(), 'dist', '.sks-build-stamp.json'), null);
114
+ return Number.isFinite(stamp?.built_at_source_time) && stamp.built_at_source_time > 0
115
+ ? stamp.built_at_source_time
116
+ : null;
117
+ }
118
+ async function loadFirstCompleteSkillsManifest(candidates) {
119
+ for (const file of candidates) {
120
+ const data = await readJson(file, null);
121
+ if (data?.schema !== PACKAGED_SKILLS_MANIFEST_SCHEMA
122
+ || data?.package_version !== PACKAGE_VERSION
123
+ || !Array.isArray(data.skills))
124
+ continue;
125
+ const normalized = normalizeSkillsManifest(data);
126
+ if (!skillsManifestHasContentDigests(normalized))
127
+ continue;
128
+ return normalized;
129
+ }
130
+ return null;
131
+ }
132
+ function skillsManifestHasContentDigests(manifest) {
133
+ const skills = Array.isArray(manifest?.skills) ? manifest.skills : [];
134
+ if (!skills.length)
135
+ return false;
136
+ const names = new Set();
137
+ for (const skill of skills) {
138
+ const name = canonicalSkillNameFromValue(skill?.canonical_name);
139
+ if (!name
140
+ || names.has(name)
141
+ || typeof skill?.content_sha256 !== 'string'
142
+ || !/^[a-f0-9]{64}$/i.test(skill.content_sha256))
143
+ return false;
144
+ names.add(name);
145
+ }
146
+ return buildFallbackSkillsManifest().skills.every((skill) => (names.has(canonicalSkillNameFromValue(skill.canonical_name))));
147
+ }
148
+ function packageRootDir() {
149
+ return path.resolve(process.env.SKS_BUILD_SOURCE_ROOT
150
+ || path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..'));
151
+ }
@@ -1,7 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import fsp from 'node:fs/promises';
3
3
  import os from 'node:os';
4
- import { fileURLToPath } from 'node:url';
5
4
  import { ensureDir, exists, nowIso, PACKAGE_VERSION, readJson, readText, sha256, withScratchDir, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
6
5
  import { buildSksCoreSkillManifest, isCoreSkillName, legacyCoreSkillNames } from '../codex-native/core-skill-manifest.js';
7
6
  import { syncCoreSkillsIntegrity } from '../codex-native/core-skill-integrity.js';
@@ -18,81 +17,16 @@ import { AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_
18
17
  import { prefixKnownSksDollarReferences, sksPrefixedSkillName } from '../routes/dollar-prefix.js';
19
18
  import { escapeRegExp } from '../text/regex.js';
20
19
  import { compactSkillDiscoveryDescription, renderSkillAgentMetadata, skillFrontmatterDescription } from '../skills/skill-agent-metadata.js';
21
- const SKS_SKILL_MANIFEST_FILE = '.sks-generated.json';
22
- const PACKAGED_SKILLS_MANIFEST_SCHEMA = 'sks.skills-manifest.v1';
23
- const SKILLS_HASH_LEDGER_SCHEMA = 'sks.skills-hash-ledger.v1';
20
+ import { REMOVED_SKS_SKILL_NAMES, LEGACY_UNPREFIXED_SKS_SKILL_NAMES, LEGACY_SKS_SUPPORT_SKILL_NAMES, PACKAGED_SKILLS_MANIFEST_SCHEMA, REMOVED_SKS_SKILL_NAME_SET, RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES, RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET, SKILL_ALIASES, SKS_SKILL_MANIFEST_FILE, SKS_SKILL_NAMES_TO_CLEAN_UP, canonicalSkillNameFromValue } from './skills/inventory.js';
21
+ import { listSkillDirs, pruneProjectGeneratedManifest, rootFromSkillsDir } from './skills/filesystem.js';
22
+ import { loadBundledSkillsManifest, loadSkillsManifest, mergePackagedSkillsManifestHashHistory, normalizeSkillsManifest, runtimeBuildSourceTime, skillManifestGenerationSha256, skillsManifestFromHashLedger } from './skills/manifest.js';
23
+ export { REMOVED_SKS_SKILL_NAMES, LEGACY_UNPREFIXED_SKS_SKILL_NAMES } from './skills/inventory.js';
24
+ export { loadBundledSkillsManifest, loadSkillsManifest, mergePackagedSkillsManifestHashHistory, skillsManifestFromHashLedger } from './skills/manifest.js';
24
25
  const MANAGED_SKILL_MARKER_VERSION = '1';
25
- const MAX_SKILL_HASH_HISTORY = 8;
26
26
  const GENERATED_PRUNE_POLICY = 'remove_previous_sks_generated_paths_absent_from_current_manifest';
27
27
  const REFLECTION_MEMORY_PATH = '.sneakoscope/memory/q2_facts/post-route-reflection.md';
28
28
  const MANAGED_SKILL_MARKER_RE = /BEGIN SKS (?:IMMUTABLE CORE|MANAGED) SKILL/;
29
29
  const FORGE_SKILL_MARKER_RE = /BEGIN SKS FORGE SKILL/;
30
- const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES = [
31
- 'sks-ux-review',
32
- 'sks-visual-review',
33
- 'sks-ui-ux-review'
34
- ];
35
- const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET = new Set(RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES);
36
- export const REMOVED_SKS_SKILL_NAMES = [
37
- 'old-workflow',
38
- 'team-legacy',
39
- 'team',
40
- 'agent-team',
41
- 'agent',
42
- 'mad-db',
43
- 'tmux',
44
- 'xai',
45
- 'swarm',
46
- 'shadow-clone',
47
- 'shadow-clone-legacy',
48
- 'kage-bunshin',
49
- 'qaloop',
50
- 'wiki-refresh',
51
- 'wikirefresh',
52
- 'research-discovery',
53
- 'sks-research-discovery',
54
- 'ralph',
55
- 'ralph-supervisor',
56
- 'ralph-resolver',
57
- 'loop',
58
- 'sks-loop'
59
- ];
60
- const LEGACY_SKS_SUPPORT_SKILL_NAMES = [
61
- 'autoresearch-loop',
62
- 'context7-docs',
63
- 'db-safety-guard',
64
- 'design-artifact-expert',
65
- 'design-system-builder',
66
- 'design-ui-editor',
67
- 'from-chat-img',
68
- 'getdesign-reference',
69
- 'gx-visual-generate',
70
- 'gx-visual-read',
71
- 'gx-visual-validate',
72
- 'honest-mode',
73
- 'hproof-claim-ledger',
74
- 'hproof-evidence-bind',
75
- 'imagegen',
76
- 'imagegen-source-scout',
77
- 'performance-evaluator',
78
- 'pipeline-runner',
79
- 'prompt-pipeline',
80
- 'reasoning-router',
81
- 'reflection',
82
- 'solution-scout',
83
- 'turbo-context-pack'
84
- ];
85
- export const LEGACY_UNPREFIXED_SKS_SKILL_NAMES = Array.from(new Set([
86
- ...LEGACY_DOLLAR_SKILL_NAMES,
87
- ...legacyCoreSkillNames(),
88
- ...LEGACY_SKS_SUPPORT_SKILL_NAMES
89
- ].map((name) => canonicalSkillNameFromValue(name)).filter((name) => name && name !== 'sks'))).sort();
90
- const SKS_SKILL_NAMES_TO_CLEAN_UP = Array.from(new Set([
91
- ...REMOVED_SKS_SKILL_NAMES,
92
- ...LEGACY_UNPREFIXED_SKS_SKILL_NAMES
93
- ]));
94
- const REMOVED_SKS_SKILL_NAME_SET = new Set(SKS_SKILL_NAMES_TO_CLEAN_UP);
95
- const SKILL_ALIASES = {};
96
30
  function reflectionInstructionText(commandPrefix = 'sks') {
97
31
  return `Post-route reflection: full routes load \`reflection\` after work/tests and before final; DFix/Answer/Help/Wiki/SKS discovery are exempt. Write reflection.md; record only real misses/gaps, or no_issue_acknowledged. For lessons, append TriWiki claim rows to ${REFLECTION_MEMORY_PATH}. Run "${commandPrefix} wiki refresh" or pack, validate, then pass reflection-gate.json.`;
98
32
  }
@@ -954,96 +888,6 @@ async function quarantineSkillDir(root, sourceDir, name, reason) {
954
888
  }
955
889
  return target;
956
890
  }
957
- export async function loadSkillsManifest() {
958
- const bundled = await loadBundledSkillsManifest();
959
- if (bundled)
960
- return bundled;
961
- const candidates = [
962
- path.join(path.resolve(process.env.HOME || os.homedir()), '.agents', 'skills', 'skills-manifest.json')
963
- ];
964
- return (await loadFirstCompleteSkillsManifest(candidates)) || buildFallbackSkillsManifest();
965
- }
966
- export async function loadBundledSkillsManifest() {
967
- const packaged = await loadFirstCompleteSkillsManifest([
968
- path.join(packageRootDir(), 'dist', 'config', 'skills-manifest.json'),
969
- path.join(packageRootDir(), 'config', 'skills-manifest.json')
970
- ]);
971
- if (packaged)
972
- return packaged;
973
- const ledger = await readJson(path.join(packageRootDir(), 'config', 'skills-hash-ledger.v1.json'), null);
974
- return skillsManifestFromHashLedger(ledger);
975
- }
976
- async function loadFirstCompleteSkillsManifest(candidates) {
977
- for (const file of candidates) {
978
- const data = await readJson(file, null);
979
- if (data?.schema !== PACKAGED_SKILLS_MANIFEST_SCHEMA
980
- || data?.package_version !== PACKAGE_VERSION
981
- || !Array.isArray(data.skills))
982
- continue;
983
- const normalized = normalizeSkillsManifest(data);
984
- if (!skillsManifestHasContentDigests(normalized))
985
- continue;
986
- return normalized;
987
- }
988
- return null;
989
- }
990
- function skillsManifestHasContentDigests(manifest) {
991
- const skills = Array.isArray(manifest?.skills) ? manifest.skills : [];
992
- if (!skills.length)
993
- return false;
994
- const names = new Set();
995
- for (const skill of skills) {
996
- const name = canonicalSkillNameFromValue(skill?.canonical_name);
997
- if (!name
998
- || names.has(name)
999
- || typeof skill?.content_sha256 !== 'string'
1000
- || !/^[a-f0-9]{64}$/i.test(skill.content_sha256)) {
1001
- return false;
1002
- }
1003
- names.add(name);
1004
- }
1005
- return buildFallbackSkillsManifest().skills.every((skill) => (names.has(canonicalSkillNameFromValue(skill.canonical_name))));
1006
- }
1007
- export function skillsManifestFromHashLedger(ledger) {
1008
- if (ledger?.schema !== SKILLS_HASH_LEDGER_SCHEMA || !Array.isArray(ledger?.skills)) {
1009
- return null;
1010
- }
1011
- const expected = new Set(buildFallbackSkillsManifest().skills.map((skill) => canonicalSkillNameFromValue(skill.canonical_name)));
1012
- const names = new Set();
1013
- const skills = [];
1014
- for (const row of ledger.skills) {
1015
- const canonicalName = canonicalSkillNameFromValue(row?.canonical_name);
1016
- const trusted = Array.isArray(row?.trusted_sha256)
1017
- ? row.trusted_sha256.map((value) => String(value || '').trim().toLowerCase())
1018
- : [];
1019
- if (!canonicalName
1020
- || canonicalName !== row?.canonical_name
1021
- || names.has(canonicalName)
1022
- || trusted.length < 1
1023
- || trusted.length > MAX_SKILL_HASH_HISTORY + 1
1024
- || trusted.some((digest) => !/^[a-f0-9]{64}$/.test(digest))
1025
- || new Set(trusted).size !== trusted.length) {
1026
- return null;
1027
- }
1028
- names.add(canonicalName);
1029
- skills.push({
1030
- canonical_name: canonicalName,
1031
- type: isCoreSkillName(canonicalName) ? 'core' : 'official',
1032
- content_sha256: trusted[0],
1033
- hash_history: trusted.slice(1),
1034
- deprecated_aliases: SKILL_ALIASES[canonicalName] || []
1035
- });
1036
- }
1037
- if ([...expected].some((name) => !names.has(name))) {
1038
- return null;
1039
- }
1040
- const manifest = {
1041
- schema: PACKAGED_SKILLS_MANIFEST_SCHEMA,
1042
- package_version: PACKAGE_VERSION,
1043
- skills: skills.sort((left, right) => (left.canonical_name.localeCompare(right.canonical_name)))
1044
- };
1045
- return skillsManifestHasContentDigests(manifest) ? manifest : null;
1046
- }
1047
891
  async function quarantineUntrustedGlobalManagedSkills(root, targetDir, manifest) {
1048
892
  const trusted = new Map();
1049
893
  for (const row of Array.isArray(manifest?.skills) ? manifest.skills : []) {
@@ -1077,55 +921,6 @@ async function quarantineUntrustedGlobalManagedSkills(root, targetDir, manifest)
1077
921
  }
1078
922
  return [...new Set(quarantined)].sort();
1079
923
  }
1080
- function skillManifestGenerationSha256(manifest) {
1081
- if (manifest?.schema !== PACKAGED_SKILLS_MANIFEST_SCHEMA || !Array.isArray(manifest?.skills)) {
1082
- return null;
1083
- }
1084
- const rows = manifest.skills
1085
- .map((skill) => ({
1086
- canonical_name: canonicalSkillNameFromValue(skill?.canonical_name),
1087
- content_sha256: String(skill?.content_sha256 || '').trim().toLowerCase()
1088
- }))
1089
- .filter((skill) => (skill.canonical_name && /^[a-f0-9]{64}$/.test(skill.content_sha256)))
1090
- .sort((left, right) => left.canonical_name.localeCompare(right.canonical_name));
1091
- return rows.length ? sha256(JSON.stringify(rows)) : null;
1092
- }
1093
- function normalizeSkillsManifest(manifest) {
1094
- const skills = (manifest.skills || [])
1095
- .map((skill) => ({
1096
- ...skill,
1097
- deprecated_aliases: (skill.deprecated_aliases || [])
1098
- .filter((name) => !REMOVED_SKS_SKILL_NAME_SET.has(canonicalSkillNameFromValue(name)))
1099
- }))
1100
- .filter((skill) => !REMOVED_SKS_SKILL_NAME_SET.has(canonicalSkillNameFromValue(skill.canonical_name)));
1101
- const { removed_skills: _retiredInventory, ...current } = manifest || {};
1102
- return { ...current, skills };
1103
- }
1104
- export function mergePackagedSkillsManifestHashHistory(currentManifest, previousManifest) {
1105
- const previousByName = new Map((Array.isArray(previousManifest?.skills) ? previousManifest.skills : [])
1106
- .map((row) => [canonicalSkillNameFromValue(row?.canonical_name), row])
1107
- .filter(([name]) => Boolean(name)));
1108
- return {
1109
- ...currentManifest,
1110
- skills: (Array.isArray(currentManifest?.skills) ? currentManifest.skills : [])
1111
- .map((row) => {
1112
- const canonicalName = canonicalSkillNameFromValue(row?.canonical_name);
1113
- const currentDigest = String(row?.content_sha256 || '').trim().toLowerCase();
1114
- const previous = previousByName.get(canonicalName);
1115
- const history = [
1116
- previous?.content_sha256,
1117
- ...(Array.isArray(previous?.hash_history) ? previous.hash_history : []),
1118
- ...(Array.isArray(row?.hash_history) ? row.hash_history : [])
1119
- ]
1120
- .map((value) => String(value || '').trim().toLowerCase())
1121
- .filter((value, index, values) => (/^[a-f0-9]{64}$/.test(value)
1122
- && value !== currentDigest
1123
- && values.indexOf(value) === index))
1124
- .slice(0, MAX_SKILL_HASH_HISTORY);
1125
- return { ...row, hash_history: history };
1126
- })
1127
- };
1128
- }
1129
924
  export async function generatePackagedSkillsManifest() {
1130
925
  return withScratchDir('skills-manifest-', async (dir) => {
1131
926
  await installOfficialSkills(dir);
@@ -1154,115 +949,6 @@ export async function writePackagedSkillManifest(targetDir, manifest) {
1154
949
  await writeJsonAtomic(file, manifest);
1155
950
  return file;
1156
951
  }
1157
- function buildFallbackSkillsManifest() {
1158
- const names = new Set([
1159
- ...DOLLAR_SKILL_NAMES.map((name) => canonicalSkillNameFromValue(name)),
1160
- ...RECOMMENDED_SKILLS.map((name) => canonicalSkillNameFromValue(name)),
1161
- ...DOLLAR_COMMANDS.map((command) => canonicalSkillNameFromValue(String(command.command || '').replace(/^\$/, ''))),
1162
- ...buildSksCoreSkillManifest().skills.map((skill) => skill.canonical_name)
1163
- ].filter((name) => Boolean(name)
1164
- && !REMOVED_SKS_SKILL_NAME_SET.has(String(name))
1165
- && !RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET.has(String(name))));
1166
- return {
1167
- schema: PACKAGED_SKILLS_MANIFEST_SCHEMA,
1168
- package_version: PACKAGE_VERSION,
1169
- skills: [...names].sort().map((name) => ({
1170
- canonical_name: name,
1171
- type: isCoreSkillName(name) ? 'core' : 'official',
1172
- content_sha256: '',
1173
- hash_history: [],
1174
- deprecated_aliases: SKILL_ALIASES[name] || []
1175
- }))
1176
- };
1177
- }
1178
- async function listSkillDirs(targetDir, opts = {}) {
1179
- const boundary = rootFromSkillsDir(targetDir);
1180
- let rootInspection;
1181
- try {
1182
- rootInspection = await inspectConfinedPath(boundary, targetDir);
1183
- }
1184
- catch (error) {
1185
- if (nodeErrorCode(error) === 'ENOENT')
1186
- return [];
1187
- throw error;
1188
- }
1189
- if (!rootInspection.exists)
1190
- return [];
1191
- if (rootInspection.leafSymlink || !rootInspection.stat?.isDirectory()) {
1192
- throw new Error(`skill_target_not_safe_directory:${targetDir}`);
1193
- }
1194
- const rows = await fsp.readdir(targetDir, { withFileTypes: true });
1195
- const out = [];
1196
- for (const row of rows) {
1197
- const dir = path.join(targetDir, row.name);
1198
- const directoryCanonical = canonicalSkillNameFromValue(row.name);
1199
- if (row.isSymbolicLink() || !row.isDirectory()) {
1200
- if (opts.includeUnsafeEntries) {
1201
- out.push({
1202
- name: row.name,
1203
- dir,
1204
- skillMdPath: null,
1205
- text: '',
1206
- canonical: directoryCanonical,
1207
- declaredCanonical: '',
1208
- directoryCanonical,
1209
- hash: '',
1210
- unsafeEntry: row.isSymbolicLink() ? 'symlink' : 'non-directory'
1211
- });
1212
- }
1213
- continue;
1214
- }
1215
- const skillMdPath = path.join(dir, 'SKILL.md');
1216
- const inspected = await inspectConfinedPath(boundary, skillMdPath);
1217
- if (!inspected.exists || inspected.leafSymlink || !inspected.stat?.isFile()) {
1218
- if (opts.includeUnsafeEntries) {
1219
- out.push({
1220
- name: row.name,
1221
- dir,
1222
- skillMdPath,
1223
- text: '',
1224
- canonical: directoryCanonical,
1225
- declaredCanonical: '',
1226
- directoryCanonical,
1227
- hash: '',
1228
- unsafeEntry: inspected.leafSymlink ? 'skill-file-symlink' : 'missing-or-non-file-skill'
1229
- });
1230
- }
1231
- continue;
1232
- }
1233
- const text = await fsp.readFile(skillMdPath, 'utf8');
1234
- const displayName = /^name:\s*(.+)\s*$/m.exec(text)?.[1] || row.name;
1235
- const declaredCanonical = canonicalSkillNameFromValue(displayName);
1236
- out.push({
1237
- name: row.name,
1238
- dir,
1239
- skillMdPath,
1240
- text,
1241
- canonical: declaredCanonical,
1242
- declaredCanonical,
1243
- directoryCanonical,
1244
- hash: sha256(text)
1245
- });
1246
- }
1247
- return out;
1248
- }
1249
- function rootFromSkillsDir(targetDir) {
1250
- const normalized = path.resolve(targetDir);
1251
- if (path.basename(normalized) === 'skills' && path.basename(path.dirname(normalized)) === '.agents') {
1252
- return path.dirname(path.dirname(normalized));
1253
- }
1254
- return path.dirname(path.dirname(normalized));
1255
- }
1256
- function canonicalSkillNameFromValue(value) {
1257
- return String(value || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
1258
- }
1259
- function packageRootDir() {
1260
- return path.resolve(process.env.SKS_BUILD_SOURCE_ROOT
1261
- || path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..'));
1262
- }
1263
- async function pruneProjectGeneratedManifest(targetDir) {
1264
- await fsp.rm(path.join(targetDir, SKS_SKILL_MANIFEST_FILE), { force: true }).catch(() => undefined);
1265
- }
1266
952
  function generatedSkillFiles(skillNames) {
1267
953
  return skillNames.flatMap((name) => [
1268
954
  `.agents/skills/${name}/SKILL.md`,
@@ -1301,12 +987,6 @@ async function writeGeneratedSkillManifest(root, skillNames) {
1301
987
  files: generatedSkillFiles(skillNames)
1302
988
  });
1303
989
  }
1304
- async function runtimeBuildSourceTime() {
1305
- const stamp = await readJson(path.join(packageRootDir(), 'dist', '.sks-build-stamp.json'), null);
1306
- return Number.isFinite(stamp?.built_at_source_time) && stamp.built_at_source_time > 0
1307
- ? stamp.built_at_source_time
1308
- : null;
1309
- }
1310
990
  async function removeStaleGeneratedSkillsFromManifest(root, skillNames) {
1311
991
  const previous = await readJson(generatedSkillManifestPath(root), null);
1312
992
  const previousSkills = Array.isArray(previous?.skills) ? previous.skills : [];